构造函数

默认构造函数

C++在类的构造中有以下确定行为:

  1. 当一个类作为数据成员时,其一定会被初始化

  2. 当内置类型(int、double、char、数组、指针)作为数据成员时,默认不进行初始化

  3. 当一个类中含有虚函数,或者类继承自一个继承单链,继承了基类的虚函数。则虚函数表指针(vptr)将会被初始化

  4. 当一个类继承自虚有基类时,编译器可能会在基类中插入一个指针用于对基类进行存取操作,该指针将被初始化。

  5. 基类构造函数必定会被执行。

当继承自虚有基类时,更多的解释如下:

考虑以下代码:

class X{
public:
    int i = 10;
};

class A : virtual public X{};

class B : virtual public X{};

class C: public A, public B{};

void func(const A* pa){
    pa->i = 1024;
}

其继承结构如下:

image

由于类型 A 的实际类型可变,编译器需要改变 执行存取操作的代码 ,导致 X::i 的实际偏移位置在内存中可能在运行时才能确定。cfront 最初的做法在派生类中的每一个虚有基类中插入一个指针,所有 对基类执行存取的操作 都可以通过该指针完成,此时, pa→i 可能被改写为:pa→_vbcX→i = 1024

其中 _vbcX 是由编译器生成的、指向虚有基类 X 的指针。该指针必定会被初始化。

为了完成以上任务,编译器在编译器可能做出以下行为:

  1. 当类不提供构造函数时,合成默认构造函数用于执行初始化代码

  2. 当类提供了构造函数,但是没有提供默认构造函数时,编译器将会在每个构造函数前加入初始化代码。

  • 在合成默认构造函数中,将会调用类成员的默认构造函数对类成员进行构造,类成员的初始化顺序与其声明顺序相同

  • 若数据成员全为内置类型,虽然编译器会合成默认构造函数,但是该默认构造函数不会执行任何操作。

  • 所谓的 初始化代码 包括:初始化类成员、vptr、用于对基类执行存取操作的指针、基类的构造函数。以上代码仅在未显式初始化时才会由编译器生成

拷贝构造函数

编译器在类处于以下情形时将会合成拷贝构造函数:

  • 数据成员中包含类成员

  • 若基类含有拷贝构造函数,则子类会合成拷贝构造函数

  • 类中含有虚函数

  • 类派生自一个包含虚有基类的继承链

之所以虚函数与拷贝构造函数相关,是因为对象在被拷贝时必须要重新设定vptr(而不能简单地将vptr的内容拷贝到另一个类中),这点与普通指针的 浅拷贝 不同,vptr 必须执行 深拷贝

Last moify: 2024-11-22 02:16:03
Build time:2025-07-18 09:41:42
Powered By asphinx