在初始化变量之前调用父类构造函数

Are parent class constructors called before initializing variables?

本文关键字:调用 父类 构造函数 初始化 变量      更新时间:2023-10-16

父类构造函数是在初始化变量之前调用的,还是编译器会先初始化类的变量?

例如

:

class parent {
  int a;
public:
  parent() : a(123) {};
};
class child : public parent {
  int b;
public:
            // question: is parent constructor done before init b?
  child() : b(456), parent() {};
}

可以,在派生类成员和构造函数体执行之前初始化基类。

12.6.2初始化基和成员[class.base.init]

在非委托构造函数中,初始化在以下订单:

-首先,并且仅用于most的构造函数派生类(1.8)、虚基类按顺序初始化它们出现在有向对象的深度优先的从左到右遍历中基类的无环图,其中"从左到右"的顺序是基类在派生类中的外观base-specifier-list .

-然后,直接基类初始化按照它们出现在基指定符列表中的顺序声明(不管初始化式的顺序如何)

-然后是非静态的类中声明数据成员的顺序初始化类定义(同样不考虑mem-initializers)。

-最后,的复合语句构造函数体被执行。

是的,父类构造函数总是在派生类之前被调用。否则,派生类不能"修改"父类设置的内容。

作为一些建议,如果您不确定,通常可以自己测试一下:

#include <iostream>
using namespace std;
class parent {
protected:
  int a;
public:
  parent() : a(123) { cout << "in parent(): a == " << a << endl; };
};
class child : public parent {
  int b;
public:
            // question: is parent constructor done before init b?
  child() : b(456), parent() { cout << "in child(): a == " << a << ", b == " << b << endl; };
};
int main() {
  child c;
  return 0;
}

打印

in parent(): a == 123
in child(): a == 123, b == 456

从基构造函数之前初始化成员重定向。可能吗?…对于一些不完全是重复的单元选择,有一个解决方案:

通过多重继承,值可以在基类之前初始化。

class parent {
    int a;
public:
    parent(int b) : a{123 + b} {};
};
class cousin {
protected:
    cousin() : b {456} {}
    int b;
};
class child : public cousin, public parent {
public:
    child() : cousin(), parent(b) {};
};

现在可以初始化b并在parent中使用。

是的,对象的构造从父类开始,到子类,所以构造函数调用是按这个顺序进行的。在破坏的情况下,这正好相反。

认为派生类是对其基类的额外添加或扩展,添加所以它添加了一些东西(这个东西必须已经存在)。然后,另一个问题是成员的初始化。这里,您提供了默认构造函数

public:
  parent() : a(123) {};

所以成员将默认初始化为123,即使你这样创建parent:

parent p;

如果没有默认构造函数用value

初始化对象
class parent {
public:
  int a;
};

比member中的默认值要高,这取决于,如果类是P.O.D,则int将默认初始化为0,但如果不是,也就是说,你提供了更多的成员,如string或vector

class parent {
public:
  int a;
  std::string s;
  std::vector<int> v;
};
如果没有默认构造函数初始化,

int将具有随机值。

可以绕过语言,在调用基类之前构造类成员。我是这样做的:

class C
{
};
class A
{
  public:
  A(C *ptr);
};
class B : public A
{
    public:
    B() : A(allocateC()) {}
    private:
    C *m_ptr;
    C *allocateC() { m_ptr = new C; return m_ptr; }
};

我目前正在研究如何使用placement new将初始化的类成员存储到类对象内存中,而不是将它们放在堆上。