如果一个类没有任何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 constructorA 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 objectB 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 constructorvirtual 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使其满足编译器的需要。