当前位置: 首页 > news >正文

【C++基础篇】学习C++就看这篇--->类和对象之static成员、友元、内部类、匿名对象

一、static成员背景如果我们要实现一个类这个类可以计算它总共实例化出多少个对象该咋实现呢相信以现阶段的知识而言肯定会说建立一个全局变量再类的构造函数和拷贝构造函数当中进行解释类要实例化出对象就必然要调用构造函数或者是拷贝构造函数如下所示代码语言javascriptAI代码解释int n 0; class A { public: A() { n; } A(const A t) { n; } private: };但这里会遇到一个问题如果其它地方把n改了呢这是不是违背了我们类的封装性的特性啊你n随便改能行所以static成员来了。✨1.1 概念声明为static的类成员称为类的静态成员用static修饰的成员变量称之为静态成员变量用static修饰的成员函数称之为静态成员函数。静态成员变量一定要在类外进行初始化如何用呢代码语言javascriptAI代码解释class A { public: A() { _scount; } A(const A t) { _scount; } static int GetACount() { return _scount; }//当然这个成员函数也可以被static修饰 //但是这样做了在函数体内就不能对非静态成员进行访问即没有this指针 private: static int _scount;//这里只是声明这样写_scount即属于这个类又属于每一个对象 }; int A::_scount 0;//这里才是定义 void TestA() { cout A::GetACount() endl;//当然如果定义成static成员想要获取就需要写一个成员函数 A a1, a2; A a3(a1); cout A::GetACount() endl; //如果将私有限定符改成公有的下面是都可以访问的 /*cout a1._secount endl; cout a2._secount endl; cout A::_secount endl;*/ } int main() { TestA(); return 0; }✨1.2 特性1️⃣静态成员为所有类对象所共享不属于某个具体的对象存放在静态区2️⃣静态成员变量必须在类外定义定义时不添加static关键字类中只是声明3️⃣ 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问4️⃣ 静态成员函数没有隐藏的this指针不能访问任何非静态成员5️⃣静态成员也是类的成员受public、protected、private 访问限定符的限制学了以上知识看两个小问题 1. 静态成员函数可以调用非静态成员函数吗 2. 非静态成员函数可以调用类的静态成员函数吗 答 1. 显然是不可以的静态成员函数是没有this指针的要调用非静态成员函数必须将对象地址传给非静态成员函数这一步是隐藏的 2. 显然是可以的无需解释。总结一下代码语言javascriptAI代码解释class A { public: static int GetACount() { return _scount; }//当然这个成员函数也可以被static修饰 private: static int _scount;//这里只是声明这样写_scount即属于这个类又属于每一个对象 }; int A::_scount 0;//这里才是定义 void TestA() { cout A::GetACount() endl;//当然如果定义成static成员想要获取就需要写一个成员函数 cout a1.GetACount() endl; }1. 如果想要访问私有static成员必须要写一个成员函数来获取2. 如果是static成员函数上述A::GetACount()和a1.GetACount()都可以使用但如果是普通成员函数就必须使用特定对象调用的方式a1.GetACount()二、友元友元提供了一种突破封装的方式有时提供了便利。但是友元会增加耦合度破坏了封装所以友元不宜多用。友元分为友元函数和友元类✨2.1 友元函数背景如上面Time类的几个成员变量是在私有限定符下这就导致了在类外面是不能访问的但是如果我必须要访问怎么办这就违背了限定符的作用那怎么办取个折中的方法你可以访问但是前提你必须是我的朋友所以友元函数就是解决上述问题的友元函数定义见下代码语言javascriptAI代码解释class Time { friend void f(Time t); private: int _hour 0; int _minute 0; int _second 0; }; void f(Time t) { t._hour 10; cout t._hour t._minute t._second endl; }有没有感觉莫名奇妙的韵味你既然要访问还弄这杂七杂八的干嘛直接定义成成员函数不就行了确实是这个样但是友元函数也确实有它的应用场景见下前面的学习过程中我们打印都是写一个print函数但是我们能不能像cout那样直接打印呢代码语言javascriptAI代码解释cout t;这样肯定是不行的就像前面学习的运算符重载那样直接用是不行的所以要想使用上面的这种形式就必须重载代码语言javascriptAI代码解释void operator(ostream out)//ostream是iostream中cout对象类型 { out _hour _minute _second endl; }但你会发现还是编不过原因就是讲述运算符重载时说过左操作数是重载函数的第一个参数即隐含的this指针右操作数是重载函数的显式形参但你现在所表达的是cout是左操作数t是右操作数因而不行代码语言javascriptAI代码解释t cout;//所以要用只能这种形式但这不符合常规啊可读性不好那怎么办this指针是隐含的而且我们知道它必须是第一个参数变不了因此友元函数的作用来了代码语言javascriptAI代码解释class Time { public: friend void operator(ostream out, const Time t1); Time(int hour 0, int minute 0, int second 0) :_hour(hour) , _minute(minute) ,_second(second) {} private: int _hour 0; int _minute 0; int _second 0; }; void operator(ostream out, const Time t1)//ostream是iostream中cout对象类型 { out t1._hour t1._minute t1._second endl; } int main() { Time t(20, 14, 50); //我们将重载函数定义到类外面 cout t; return 0; }补充知识 ostream是iostream中cout对象类型 istram是iostream中cin对象类型cout我们一般还有这样操作过代码语言javascriptAI代码解释cout i j endl;连续的输出但是我们上面所实现的并不能完成上面功能 需要如下做代码语言javascriptAI代码解释ostream operator(ostream out, const Time t1)//ostream是iostream中cout对象类型 { out t1._hour t1._minute t1._second endl; return out; }我们还有输入cin原理和上面类似连续输入的实现如下代码语言javascriptAI代码解释istream operator(istream in, Time t1)//istream是iostream中cin对象类型 { in t1._hour t1._minute t1._second ; return in; }注意友元函数可访问类的私有和保护成员但不是类的成员函数友元函数不能用const修饰友元函数可以在类定义的任何地方声明不受类访问限定符限制一个函数可以是多个类的友元函数友元函数的调用与普通函数的调用原理相同总结一下友元函数在 C 中的主要应用场景是当某个函数需要直接访问一个类的私有或保护成员但该函数逻辑上又不应该或不能是这个类的成员函数时。它打破了严格的封装边界但提供了必要的灵活性。
http://www.zskr.cn/news/1399911.html

相关文章:

  • 用Unity UGUI打造游戏内的可折叠技能树或背包系统:基于Hierarchy视图的UI设计思路
  • AI安全新范式:从能力竞赛到风险管控,Anthropic的“危险模型”启示
  • 模型安全扫描器失效:29种绕过技术揭示PyTorch与Hugging Face模型加载风险
  • CentOS 7服务器配置实录:用yum安装PHP 8.1并搞定常用扩展(bcmath, gd, pdo_mysql...)
  • Spectrasonics Trilian 1.6.6D:音乐人公认的四大顶级贝斯合成器之一,全面解析与下载
  • 打印机租赁的“进化简史”
  • 「新品发布」全新Alicona µCMM NEO微米级三坐标测量系统正式亮相
  • Git 代码误删除恢复
  • Azure开发者工具智能化与数据库成本优化实战指南
  • Windows 10/11 用户福音:手把手教你用注册表让OneDrive选择性同步(避开那些烦人的临时文件)
  • wsl2+ubuntu22.04配置docker代理
  • Keil MDK编译器警告级别设置问题解析与解决方案
  • 保姆级教程:用DPABI和Matlab给脑图做‘分区体检’,提取AAL90模板特征
  • Seatable 4.3 数据迁移翻车实录:从Ubuntu到CentOS,我踩了哪些坑?
  • 如何搭建第一个AI智能体?零代码Coze完整教程
  • 商品详情接口高并发架构:独立资源池与并发控制实战
  • AI智能体架构优化:将LLM移出检索路径,提升性能与降低成本
  • 使用Taotoken后API调用延迟与稳定性有哪些可观测的改善
  • 修复误删系统文件导致电脑屏幕有时黑屏问题
  • ADHD幸存者偏差
  • 面试题 - GIL全局解释器锁 :为什么Python多线程不能利用多核?GIL对I/O密集和CPU密集任务的影响?如何绕过GIL(多进程、C扩展)
  • STM32F103C8T6串口收发控制LED灯:一个标准库项目搞定硬件交互与调试
  • 纯视觉GUI智能体Mano-P:OSWorld榜首开源项目解析与实践
  • 2024年十大技术趋势抢先看
  • 行业案例|送水猫水站数字化升级实录:借助拉米云 SaaS 破解桶装水配送与管理难题
  • 靠谱的GPU整机定制服务商排名
  • Windows本地postgresql 17升级18
  • CJ 4DPLEX 与科视 Christie 续签合作协议
  • 从‘free’命令看Linux内存管理:你的服务器内存真的‘不够用’吗?
  • AI智能体实战指南:从核心架构到LangChain搭建全解析