13

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

例如:

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() {};
}
4

5 回答 5

18

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

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

在非委托构造函数中,初始化按以下顺序进行:

— 首先,并且仅对于最派生类 (1.8) 的构造函数,虚拟基类按照它们在基类的有向无环图的深度优先从左到右遍历中出现的顺序进行初始化,其中“左-to-right”是派生类基类说明符列表中基类的出现顺序。

— 然后,直接基类按照它们出现在 base-specifier-list 中的声明顺序进行初始化(无论 mem-initializers 的顺序如何)。

— 然后,非静态数据成员按照它们在类定义中声明的顺序进行初始化(同样不管 mem-initializers 的顺序)。

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

于 2013-03-12T16:26:29.567 回答
3

是的,父构造函数总是在派生类之前调用​​。否则,派生类无法“更改”父类设置的内容。

于 2013-03-12T16:23:11.063 回答
2

就像一些建议一样,如果您不确定,通常可以自己测试这样的事情:

#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
于 2013-03-12T16:27:51.483 回答
0

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

于 2013-03-12T16:47:47.510 回答
0

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

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

因此,即使您以这种方式创建父级,该成员也将默认初始化为 123:

parent p;

如果没有用值初始化对象的默认构造函数

class parent {
public:
  int a;
};

比成员的默认值取决于,如果类是 POD,则 int 将默认初始化为 0,但如果不是,即您提供更多成员,例如字符串或向量

class parent {
public:
  int a;
  std::string s;
  std::vector<int> v;
};

如果没有初始化它的默认构造函数, int 将具有随机值。

于 2013-03-12T17:01:36.443 回答