如果一個類沒有任何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使其滿足編譯器的需要。