构造函数语义学

有些书上说,如果一个类中没有任何的构造函数,那么编译器会为我们默认的合成一个“合成默认规则函数”。
其实,系统是在“必要的时候”才会为我们合成默认的构造函数。这个可以去分析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;
}

猜你喜欢

转载自blog.csdn.net/qq_38158479/article/details/106441281
今日推荐