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

类和对象(下)

大家好,这篇我们继续学习类和对象。

1. 成员初始化列表

在构造函数中,我们常常需要初始化类的成员变量。C++ 提供了两种方式:

  • 在构造函数体中赋值

  • 使用成员初始化列表

成员初始化列表的语法是在构造函数参数列表后加:,然后列出要初始化的成员。

class Date { public: Date(int year, int month, int day, int hour) : _year(year) , _month(month) , _day(day) , _t(hour) // 初始化对象成员 { // 构造函数体 } private: int _year; int _month; int _day; Time _t; // 对象成员 };
为什么推荐使用初始化列表?
  1. 效率更高:直接初始化,而不是先默认构造再赋值。

  2. 必须使用的情况

    • const成员

    • 引用成员

    • 没有默认构造函数的类类型成员

class Date { private: int& _ref; // 引用成员,必须在初始化列表中绑定 const int _n; // const 成员,必须在初始化列表中初始化 Time _t; // 如果 Time 没有默认构造函数,也必须显式初始化 };

2. 成员初始化顺序

重要提醒:成员的初始化顺序与初始化列表的书写顺序无关,只与类中成员的声明顺序有关

class A { public: A(int a1, int a2) : _a2(a2) 1,再初始化 _a2 , _a1(_a2) // 注意!这里 _a2 还未初始化,结果是未定义行为 {} private: int _a1 = 2; int _a2 = 2; };

正确做法:按照声明顺序书写初始化列表,避免依赖未初始化的成员。

3. explicit 构造函数

默认情况下,单参数构造函数会发生隐式转换,有时这会带来意外行为。

class A { public: A(int a1) : _a1(a1) {} // 如果不加 explicit,下面的转换会自动发生 private: int _a1; }; A aa = 10; // 隐式转换为 A(10)

加上explicit可以禁止这种隐式转换:

explicit A(int a1) : _a1(a1) {} A aa = 10; // 编译错误,必须显式写 A aa(10);

C++11 还支持多参数构造函数使用{}初始化列表,但 explicit 同样可以阻止隐式转换。

4. 静态成员

静态成员属于类本身,而不是对象。特点:

  • static关键字声明

  • 必须在类外定义并初始化

  • 所有对象共享同一份

class A { public: static int GetCount() { return _scount; } private: static int _scount; }; int A::_scount = 0; // 类外定义 int main() { cout << A::GetCount() << endl; // 即使没有对象也能访问 return 0; }

用静态成员实现全局计数器,或者实现 1+2+...+n 的求和(不使用循环/条件判断):

class Sum { public: Sum() { _ret += _i; ++_i; } static int GetRet() { return _ret; } private: static int _i; static int _ret; }; int Sum::_i = 1; int Sum::_ret = 0; int Sum_Solution(int n) { Sum arr[n]; // 创建 n 个对象,每个对象构造时累加 return Sum::GetRet(); }

5. 友元(friend)

友元破坏了封装,但提供了灵活性。友元可以访问类的 private/protected 成员。

  • 友元函数

  • 友元类

class B; // 前向声明 class A { friend void func(const A& a, const B& b); // 友元函数 friend class B; // 友元类 private: int _a = 1; }; class B { public: void visit(const A& a) { cout << a._a << endl; // B 是 A 的友元,可以访问 } };

6. 内嵌类(嵌套类)

类可以定义在另一个类内部,称为内嵌类。

class A { public: class B { // 内嵌类 public: void foo(const A& a) { cout << a._h << endl; // 可以访问外部类的 private 成员 } }; private: int _h = 1; static int _k; };

内嵌类默认是外部类的友元,可以直接访问外部类的所有成员(包括 static)。

7. 拷贝控制

当类管理资源时,需要自定义:

  • 拷贝构造函数

  • 拷贝赋值运算符

  • 析构函数

C++11 还增加了移动构造函数和移动赋值运算符。

class A { public: A(const A& aa) { /* 深拷贝 */ } A& operator=(const A& aa) { if (this != &aa) { /* 深拷贝 */ } return *this; } ~A() { /* 释放资源 */ } };

另外,临时对象的构造和析构要特别注意。现代编译器会进行拷贝省略,但在某些情况下仍会产生多次构造/析构。

总结

以上就是 C++ 类和对象的高级特性。

  • 优先使用初始化列表

  • 注意成员初始化顺序

  • 谨慎使用友元

  • 需要管理资源时,记得实现拷贝控制

希望这篇文章对你有帮助!

http://www.jsqmd.com/news/286015/

相关文章:

  • 2026年国产持妆粉底液厂家专业深度测评(排名前五)
  • 工业显示器在智能办公用品申领柜中的应用
  • Rust入门一:从内存安全到高性能编程
  • 从源码视角来看Pinia!
  • 2026年国产持妆粉底液专业深度测评:排名前五品牌权威发布
  • 2026年国产持妆粉底液专业深度测评:排名前五供应商权威榜单
  • 初学范畴论的一些体会
  • 2026年专业深度测评:国产持妆粉底液厂家排名前五权威榜单
  • 2026毕业论文降AI必备:这5款工具帮你AI率降到10%以下
  • 【计算机毕业设计案例】基于springboot的就业招聘面试试题管理系统(程序+文档+讲解+定制)
  • 2026年8款免费降AI率工具实测推荐,毕业生必看
  • 【计算机毕业设计案例】基于SpringBoot+Vue咖啡售卖商城平台的设计与实现基于springboot的咖啡共赏平台(程序+文档+讲解+定制)
  • 毕业生必看:知网AIGC检测不通过怎么办?超全解决方案
  • 解决 Java UnsatisfiedLinkError: libfontmanager.so 加载失败问题
  • Java毕设项目推荐-基于springboot的面试试题管理系统基于springboot面试刷题平台系统的设计与实现【附源码+文档,调试定制服务】
  • 长春婚纱照,记录下你们爱情故事中的每一个动人瞬间
  • Java毕设项目推荐-基于springboot在线咖啡点单平台基于springboot的咖啡共赏平台【附源码+文档,调试定制服务】
  • 基于微信小程序的汽车维修预约系统【源码+文档+调试】
  • 学习日记day65
  • 基于微信小程序的企业会议预约系统【源码+文档+调试】
  • 手把手教你学Simulink--风电电机控制场景实例:基于Simulink的风电变流器死区补偿与非线性校正仿真
  • 全网最全8个一键生成论文工具,本科生轻松搞定毕业论文!
  • 《创业之路》-865-创新扩散理论以及在投资、创业中的应用
  • 知网vs维普AIGC检测:哪个更严格?实测数据告诉你答案
  • 手把手教你学Simulink--风电电机控制场景实例:基于Simulink的DFIG转子电流限幅保护策略仿真
  • 手把手教你用多语言互译法降AI,10分钟搞定(附操作截图)
  • 导师推荐!8款AI论文工具测评:本科生毕业论文全攻略
  • 深度解析:为什么自己写的论文也会被判AI率很高?背后的3个真相
  • 降AIGC神器推荐!5个降AI工具助你轻松应对论文AI率,有效降低80%AI率!
  • 2026年专业深度测评:电商代运营公司排名前五权威榜单3