C++合成默认构造函数的4种情况

合成默认构造函数的4种情况(合成是为了满足编译器的需要,而不是程序的需要)

1. "带有Default Constructor"的Member Class Object

class Foo
{
    public:
        Foo();
        Foo(int);
}

//Bar包含Foo
class Bar
{
    public:
        Foo foo;
        char *str;
}

void foo_bar()
{
    Bar bar; //Bar::foo 必须在此处初始化。
}
//被合成的Bar default constructor内含必要的代码,能够调用class Foo的default construct来处理member object Bar::foo,<br>
//但它并不产生任何代码来初始化Bar::str()将Bar::str初始化则是程序员的责任。
//Bar的default constructor可能会被这样合成
//为member foo调用Class Foo的default constructor
inline Bar::Bar()
{
    //C++伪代码
    foo.Foo::Foo();
}

假设程序员经由下面的default constractor提供了str的初始化操作

//程序员定义的default constructor
Bar::Bar()
{
    str = 0;
}

编译器的行动是:“如果class A内含一个或一个以上的member class objects, 那么class A的每一个constructor必须调用每一个member classes的default constructor",编译器会扩张已存在的constructor,在其中安插一些代码,使得user code被执行之前,先调用必要的default constructor。

//扩张后的default constructor
//C++伪代码
Bar::Bar()
{
    foo.Foo::Foo();
    str = 0;
}

2. "带有Default Constructor"的Base Class。

如果一个没有任何constructors的class派生自一个“带有default constructor”的base class,那么这个derived class 的default constructor会被视为nontrivail,因此需要被合成。
如果设计者提供多个constructor,但其中都没有default constructor呢?编译器会扩张现有的每一个constructor,将“用以调用所有必要之default constructors”的程序代码加进去。

3. "带有一个virtual Function"的Class

两种情况需要合成default constructor

  1. class声明(或继承)一个virtual function.
  2. class派生自一个继承串链,其中有一个或更多的virtual base classes.

下面两个扩张行动会在编译期间发生:

  1. 一个virtual function table会被编译器产生出来,内放class 的 virtual function地址。
  2. 在每一个class object中,一个额外的pointer member(也就是vptr)会被编译器合成出来,内含相关之class vtbl的地址。

    编译器为每一个带有virtual function类的vptr设定初值,放置适当的virtual table地址。对于class所定义的每一个constractor,编译器会安插一些代码来做这样的事情,对于没有没有声明任何constructor的classes,编译器会为他们合成一个default constructor.

4. "带有一个Virtual Base Class"的Class

对于class所定义的每一个constructor,编译器会安插那些"允许每一个virtual base class的执行期存取操作"的代码,如果class没有任何constructors,编译器必须为它合成一个default constructor。

猜你喜欢

转载自blog.csdn.net/u012069234/article/details/113271977
今日推荐