目录※一、初始化列表※初始化列表使用总结构造-析构顺序练习题二、类与对象中的隐式类型转换三、static修饰类成员四、友元类、友元函数五、匿名对象六、较少应用知识点内部类对象拷贝时的编译器优化前言在了解了类和对象的基本内容之后就可以深入了解一些类与对象的拓展使用方法~※一、初始化列表前言构造函数初始化的一种方法。集中实现变量、常量的初始化赋值(秩序性、简洁性)。标注※为复习重点格式在构造函数的下一行(可在末尾)以:开头后接初始化目标名字后接()内部值决定初始化目标的值 最后加{} () 。 ()内部可以为变量、计算式。示例class Date { public: Date(int year, int month, int day) :_year(year) ,_month(month) ,_day(day) { ; // 此处可以不加但是必须加{}!! } private: int _year; int _month; int _day; };对于初始化列表有以下规定(最后总结)※1.const 对象 引用对象 没有默认构造的类类型变量必须写入初始化列表。class Date { public: Date(int year, int month, int day, int x) :_year(year) , _month(month) , _day(day) ,_t(12) ,ref(x) //注意此处的引用必须要传入变量了 ,_n(x) { ; // 此处可以不加但是必须加{}!! } private: int _year; int _month; int _day; Time _t; //没有默认构造 int ref; //引用 const int _n;//const };2.尽量写入初始化列表因为即使变量你没有写入它仍会走初始化列表(假如你在定义时就进行了初始化那么调用此缺省值 如下)class Date1 { public: Date1(int year, int month) :_year(year) , _month(month) { ; // } private: ※private区域给予初始化 实际时缺省值在进行初始化列表时假如没有 那么调用此缺省值 int _year 2007; int _month 1; int _day 28; //自动缺省初始化为28 };3.初始化列表的初始化顺序是按照声明顺序执行的而非按照初始化列表中的顺序。推荐的构造函数初始化的基本格式class Date1 { public: Date1(int year 2007, int month 1, int day 28) :_year(year) ,_month(month) ,_day(day) { } void Print() const { cout _year / _month / _day endl; return; } private: int _year; int _month; int _day; };※初始化列表使用总结1.const 对象 引用对象 没有默认构造的类类型变量必须写入初始化列表。2.尽量写入初始化列表因为即使变量你没有写入它仍会走初始化列表(假如你在定义时就进行了初始化那么调用此缺省值 如下)3.初始化列表的初始化顺序是按照声明顺序执行的而非按照初始化列表中的顺序。构造-析构顺序练习题下⾯程序的运⾏结果是什么A. 输出 1 1B. 输出 2 2C. 编译报错D. 输出 1 随机值E. 输出 1 2F. 输出 2 1#includeiostream using namespace std; class A { public: A(int a) :_a1(a) , _a2(_a1) {} void Print() { cout _a1 _a2 endl; } private: int _a2 2; int _a1 2; }; int main() { A aa(1); aa.Print(); }答案D原因分析(按照声明顺序读代码)1.先进入主函数---类的初始化。2.由于先是_a2声明先初始化_a2初始化为_a1但是此时_a1未初始化是随机值。3._a1初始化为主函数传入的1。二、类与对象中的隐式类型转换功能方便构造1.内置类型转为类类型对象需要有相关内置类型为参数的构造函数。2.在构造函数前explicit[ɪkˈsplɪsɪt] (清晰的) 表示此构造函数不再支持隐式类型转换。3.类类型的对象之间也可以隐式转换需要相应的构造函数支持。(实用价值少……文章不涉及~)#include iostream using namespace std; class Date { public: // 单参数构造函数 - 允许隐式转换 Date(int year) : _year(year) , _month(1) , _day(1) { cout Date(int) 构造: year endl; } void print() const { cout _year - _month - _day endl; } private: int _year; int _month; int _day; }; void func(Date d) { d.print(); } int main() { // 隐式类型转换发生的地方 // 初始化时 Date d1 2024; // ✅ 隐式转换int → Date d1.print(); return 0; }若隐式转换中传入多个参数其格式有Date d1;d1 {2009, 9, 1};三、static修饰类成员前言static加上后表示静态性质——存储于内存的静态区不因在类内而隶属于某一对象。↓为所有对象所共享(都可访问)1.静态成员变量一定要在类外初始化。2.静态函数没有this指针。3.静态成员受类内访问限定符限制(private pritected public)。4.由于静态成员在类内 所以规定访问必须指定如Date::valuable。5.静态成员变量不能在声明位置给初始值进行初始化 静态成员不属于任意对象不走初始化列表初始化。四、友元类、友元函数1.友元提供了一种突破类访问限定符的封装方式友元分为友元函数与友元类在函数声明或类声明前加friend并且把友元声明放到一个类的里面。2.外部友元函数可以访问类的的私有和保护成员友元函数仅仅是一种声明他表示类的成员函数。3.友元函数可以在类的任何地方声明因为其的使用不受类访问限定符的限制。4.一个函数可以是多个类的友元函数(不推荐使用)。5.友元类中的成员函数都可以是另一个类的友元函数都可以定位另一个类中的私有和保护成员。6.友元关系是单向的不具有交换性即在A类中声明友元类B那么B类可以访问A类中的私有成员。但是A类不能访问B类的私有成员。代码如下7.友元关系不能传递如A是B的友元B是C的友元但是A不是C的友元。8.友元会增加耦合度破坏了封装所以友元不宜多用。//友元的单向性 class Date1; class Date { friend class Date1; //Date2类中定义友元类Date——Date2类的友元类是Date——Date2中可以访问Date中的数据 public: //void Print(Date1 d) //{ // cout d.m endl; //err 不能访问d.m 友元类 单向性的体现 //} int n 0; }; class Date1 { public: void Print(Date d) { cout d.n endl; //可以访问d.n } int m 0; private: static int max; //类内声明 };五、匿名对象1.使用类型(实参)定义出来的对象叫做匿名对象我们之前定义的类型 名称叫做有名对象。2.匿名对象的生命周期只在当前这一行这一行结束就会析构。//匿名对象 class Date { public: Date(int a 1) { int _a a; } void Print(const Date d) const //只读成员函数 { cout d._year endl; //err 为什么不可以访问 生命周期 } private: int _year; int _month; int _day; }; int main4() { //例一. Date(); //匿名对象 Date(2); //匿名对象 //例二. Date d1; Date().Print(d1); //使用匿名对象节省了空间 return 0; }六、较少应用知识点内部类1.如果一个类定义在另一个类的内部这个内部类就佳作内部类。内部类是一个独立的类跟定义在全局相比它只是受外部类类域限制和访问限定符限制所以外部类定义的对象不包含内部类。2.内部类默认是外部类的友元类。3.内部类的本质也是一种封装当A跟B类紧密相关A类实现出来主要就是给B类使用那么可以考虑把A类设计为B的内部类如果放到private/protected位置那么A类就是B类的专属内部类其他地方都用不了。对象拷贝时的编译器优化1.现代编译器为尽可能地提高程序的效率在不影响正确性的情况下会尽可能地减少一些传参和传值返回可以省略的拷贝。2.如何优化 程度如何C没有严格规定取决于编译器。