有些书上说,如果一个类中没有任何的构造函数,那么编译器会为我们默认的合成一个“合成默认规则函数”。
其实,系统是在“必要的时候”才会为我们合成默认的构造函数。这个可以去分析obj文件
情况1:
如果一个类中没有任何的构造函数,且它的成员变量中含有一个类类型的成员,那么这个时候系统会为这个类合成一个默认的构造函数。
class A
{
public:
A()
{
cout << "aaaaa" << endl;
}
};
class C
{
public:
int c;
A a;
};
int main()
{
C c;//会调用A()
}
分析:为什么会调用A()呢?其实是编译器为类C合成了一个默认的构造函数,而这个默认构造函数又去调用A(),来初始化a,所以会调用A()
class A
{
public:
A()
{
cout << "aaaaa" << endl;
}
};
class B
{
public:
B()
{
cout << "bbbbb" << endl;
}
};
class C
{
public:
int c;
A a;
B b;
};
int main()
{
C c;
}
那么这个时候系统会先调用A(),在调用B(),调用顺序和类C中定义成员变量的顺序有关。
情况2:父类有一个默认构造函数,而子类没有构造函数时,编译器会为子类合成一个默认构造函数,从而让这个合成的默认构造函数去调用父类中的构造函数。
class A
{
public:
A()
{
cout << "aaaaa" << endl;
}
};
class B:public A
{
public:
};
int main()
{
B b;
}
情况三:一个类含有虚函数时,但没有任何构造函数时。
这种情况下,因为有虚函数的存在,所以会生成一个虚函数表,且在编译器合成的构造函数中安插代码,即,把虚函数表地址赋给了虚函数指针。
这可以通过汇编代码来看。
class A
{
public:
virtual void fun()
{
cout << "aaaaa" << endl;
}
};
A a;//只是这里不会去调用该虚函数,因为编译器安插的代码中没这么干。
情况四:当一个类带有虚基类时。
虚基类(虚继承)只会出现在三层结构中。
这里,编译器会为c合成一个默认的构造函数,同时编译器也为A,A2合成了默认构造函数。
class Grand
{
public:
int a;
};
class A:virtual public Grand//虚继承
{
public:
};
class A2 :virtual public Grand//虚继承
{
public:
};
class C :public A, public A2
{
public:
};
int main()
{
C c;
}