1、默认构造函数生成规则
编译器不一定会为类生成默认构造函数,但在下列情况下,编译器会生成默认构造函数。
(1)该类没有任何构造函数,但包含一个类类型的成员变量,且成员变量所属的类有默认构造函数。
(2)该类没有任何构造函数,但其父类有默认构造函数。
(3)该类没有任何构造函数,但含有虚函数
因为虚函数会产生虚函数表指针,而这个虚函数表指针需要在构造函数中生成。
MyDemo::MyDemo{
this->_vptr = 0x00BC;
}
(4)类带有虚基类
因为需要在构造函数中生成虚基类表指针。
MyDemo::MyDemo{
this->_vbptr = 0x00BC;
}
(5)对成员变量进行了大挂号或等号初始化。
class MyDemo{
private:
int x = 1;
int y(2)
}
编译器合成的默认构造函数如下(伪代码):
MyDemo::MyDemo{
this->x = 1;
this->y = 2;
}
2、验证默认构造函数生成规则
上面生成默认构造函数的5条规则,我们可以通过VS2019来验证。
(1)没有生成默认构造函数
class MyDemo {
};
int main()
{
MyDemo demo;
return 0;
}
我们把断点设在第8行:return 0 的位置。运行后打开“反汇编”窗口,可以看到如下代码:
(2)生成默认构造函数
给MyDemo类增加代码,使其满足第5条规则。
class MyDemo {
private:
int x = 1;
};
可以看到反汇编代码中有调用构造函数的代码:call MyDemo::MyDemo,也就是说这个时候MyDemo类生成了默认构造函数。
关于其他4条生成默认构造函数的规则,读者可以用同样的方法去验证。
3、继承中的对象构造
首先我们要知道继承中的对象构造规则:由内而外,即先构造父类对象,再构造子类对象。
我们可以用下面的代码验证继承中的对象构造顺序:
class Base {
public:
Base() { cout << "Base::Base()" << endl; }
};
class Derive : public Base {
public:
Derive() { cout << "Derive::Derive()" << endl; }
};
int main()
{
Derive derive;
return 0;
}
执行后的结果可以看到:
Base::Base()
Derive::Derive()