1. 初始化列表
构造函数和其他函数不同,除了有名字,参数列表,函数体之外还有初始化列表。
初始化列表简单使用:
class Person{ public: #if 0 //传统方式初始化 Person(int a,int b,int c){ mA = a; mB = b; mC = c; } #endif //初始化列表方式初始化 Person(int a, int b, int c):mA(a),mB(b),mC(c){} void PrintPerson(){ cout << "mA:" << mA << endl; cout << "mB:" << mB << endl; cout << "mC:" << mC << endl; } private: int mA; int mB; int mC; };
注意:初始化成员列表(参数列表)只能在构造函数使用。
2.类对象作为成员
在类中定义的数据成员一般都是基本的数据类型。但是类中的成员也可以是对象,叫做对象成员。
C++中对对象的初始化是非常重要的操作,当创建一个对象的时候,c++编译器必须确保调用了所有子对象的构造函数。如果所有的子对象有默认构造函数,编译器可以自动调用他们。但是如果子对象没有默认的构造函数,或者想指定调用某个构造函数怎么办?
那么是否可以在类的构造函数直接调用子类的属性完成初始化呢?但是如果子类的成员属性是私有的,我们是没有办法访问并完成初始化的。
解决办法非常简单:对于子类调用构造函数,c++为此提供了专门的语法,即构造函数初始化列表。
当调用构造函数时,首先按各对象成员在类定义中的顺序(和参数列表的顺序无关)依次调用它们的构造函数,对这些对象初始化,最后再调用本身的函数体。也就是说,先调用对象成员的构造函数,再调用本身的构造函数。
析构函数和构造函数调用顺序相反,先构造,后析构。
//汽车类 class Car{ public: Car(){ cout << "Car 默认构造函数!" << endl; mName = "大众汽车"; } Car(string name){ cout << "Car 带参数构造函数!" << endl; mName = name; } ~Car(){ cout << "Car 析构函数!" << endl; } public: string mName; }; //拖拉机 class Tractor{ public: Tractor(){ cout << "Tractor 默认构造函数!" << endl; mName = "爬土坡专用拖拉机"; } Tractor(string name){ cout << "Tractor 带参数构造函数!" << endl; mName = name; } ~Tractor(){ cout << "Tractor 析构函数!" << endl; } public: string mName; }; //人类 class Person{ public: #if 1 //类mCar不存在合适的构造函数 Person(string name){ mName = name; } #else //初始化列表可以指定调用构造函数 Person(string carName, string tracName, string name) : mTractor(tracName), mCar(carName), mName(name){ cout << "Person 构造函数!" << endl; } #endif void GoWorkByCar(){ cout << mName << "开着" << mCar.mName << "去上班!" << endl; } void GoWorkByTractor(){ cout << mName << "开着" << mTractor.mName << "去上班!" << endl; } ~Person(){ cout << "Person 析构函数!" << endl; } private: string mName; Car mCar; Tractor mTractor; }; void test(){ //Person person("宝马", "东风拖拉机", "赵四"); Person person("刘能"); person.GoWorkByCar(); person.GoWorkByTractor(); }