Chap2-构造函数语意学
如果一个类没有任何constructor,那么会有一个default constructor被隐式的声明出来,一个implicit default constructor将是一个trivial(无用的)constructor。但是在某些情况下,implicit default constructor将是一个nontrivial constructor,下面一一讨论:
由编译器合成nontrivial default constructor的四种情况:
1)带有default constructor 的 member class object(ps:不包括基本数据类型对象):
- case 1:如果一个类没有任何constructors,但它包含一个member class object,那么这个类的implicit default constructor 会去调用member class object的default constructor。
class A { public: A(){cout<<"Class A Constructor!"<<endl;} }; class B { public: A a; // a is a member class object and class A has a default constructor. }; void main() { B b; }
- case 2:如果一个类包含constructors(ps:不限定是default constructor),也包含带default constructor的member class object,但是没有在constructors中显示调用,那么编译器会扩张已存在的constructors,使其每个member class object得到初始化。
class A { public: A(){cout<<"Class A Constructor!"<<endl;} }; class B { public: B(int){} // Non-default constructor A a; // a is a member class object and class A has a default constructor. }; void main() { B b(5); }
- case 3:C++中以member class object 在类中的声明顺序来调用各个constructors。
class A { public: A(){cout<<"Class A Constructor!"<<endl;} // Default constructor }; class B { public: B(){cout<<"Class B Constructor!"<<endl;} // Default constructor }; class C { public: A a; // Member class object B b; // Member class object }; void main() { C c; }
2)带有default constructor 的 base class:
- case 1:如果一个类没有任何constructors,但它派生自一个或多个带有default constructor 的 base class,那么这个类的implicit default constructor 会去调用base class 的 default constructor(按声明顺序调用)。
class A { public: A(){cout<<"Class A Constructor!"<<endl;} // Default constructor }; class B : public A{}; void main() { B b; }
- case 2:如果一个类包含constructors(ps:不限定是default constructor),且派生自一个或多个带有default constructor 的 base class,但是没有在constructors中显示调用,那么编译器会扩张已存在的constructors,使其每个上层base class 的 default constructor 得到调用(按声明顺序调用)。
class A { public: A(){cout<<"Class A Constructor!"<<endl;} // Default constructor }; class B : public A { public: B(){} }; void main() { B b; }
3)带有一个或多个virtual functions 的 class:
- class声明(或继承)一个或多个virtual functions,那么编译器会在constructors(如果没有,则隐式创建一个default constructor)中隐式的进行一些扩张行动:创建一个virtual function table,内放class 的 virtual functions的地址(所以一个类中如果声明了virtual function(纯虚函数除外),就必须实现它,实现了才会有函数地址);在每一个class object中,创建一个额外的vft_ptr,内含virtual function table的地址。
// sizeof(A)=1 class A { public: A(){cout<<"Class A Constructor!"<<endl;} // Default constructor }; // sizeof(A)=4 class A { public: A(){cout<<"Class A Constructor!"<<endl;} // Default constructor virtual void foo(){} };
4)带有一个或多个virtual base class 的 class:
- class或继承一个或多个virtual base class,那么编译器会在constructors(如果没有,则隐式创建一个default constructor)中隐式的进行一些扩张行动:创建一个virtual base class table,内放virtual base class subobjects 的地址(所以要virtual派生自一个base class,那么这个base class必须提供default constructor,使得编译器能创建virtual base class 的 subobject);在每一个class object中,创建一个额外的vbt_ptr,内含virtual base class table的地址。
// sizeof(B)=1 class A{}; class B : public A{}; // sizeof(B)=4 class A{}; class B : public virtual A{};
总结:以上四种情况,会造成编译器为未声明constructor的类隐式生成一个default constructor,或者扩张已有的constructors使其满足编译器的需要。