【问题标题】:Are parent class constructors called before initializing variables?在初始化变量之前是否调用了父类构造函数?
【发布时间】:2013-02-28 06:49:35
【问题描述】:

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

例如:

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

【问题讨论】:

  • 那么你的问题是你是否可以通过初始化列表布局来控制基类构造函数和派生类成员变量的初始化顺序?
  • 一个想法,您可以通过在父构造函数和成员变量的构造函数中打印到控制台来检查这一点,但现在您得到了闪亮的答案。
  • @WhozCraig 没有。成员变量的控制是通过位置来完成的(先到先得),但我不确定是基类还是成员在先。

标签: c++ class inheritance


【解决方案1】:

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

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

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

——首先,并且仅适用于最 派生类(1.8),虚拟基类按顺序初始化 它们出现在定向的深度优先从左到右遍历 基类的无环图,其中“从左到右”是 派生类中基类的外观 基本说明符列表。

——然后​​,直接基类在 出现在基本说明符列表中的声明顺序 (不管 mem-initializers 的顺序如何)。

——那么,非静态的 数据成员按照它们在 类定义(同样不管 内存初始化器)。

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

      #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
      

      【讨论】:

      • 这没有回答问题。 b 应该是一个类,它的构造函数打印一些东西。
      • 我实际上在发布我的问题之前做了一个测试,我知道它是先用我测试的特定编译器完成的。我正在寻找的是 Luchian Grigore 的 answer 中的定义。
      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

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

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

        parent p;
        

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

        class parent {
        public:
          int a;
        };
        

        如果类是 P.O.D 则 int 将默认初始化为 0,但如果不是,即您提供更多成员,例如字符串或向量

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-21
          • 2012-06-30
          • 1970-01-01
          • 1970-01-01
          • 2017-05-12
          相关资源
          最近更新 更多