【问题标题】:Inheritance, Calling base class ctors继承,调用基类ctors
【发布时间】:2010-07-22 12:01:06
【问题描述】:
class Base{
    public:
      Base(int val):_id(val){};
      int _id;
};

class Derived : Base {
    public:
      Derived(int val):Base(_id+val){};
};

int main(){
     Derived d(60);
}

为什么这不会给出错误?基类仍未构建,但我可以使用“_id”?

谢谢

【问题讨论】:

    标签: c++ list inheritance initialization constructor


    【解决方案1】:

    一个更简单的例子:int x = x + 1; 告诉你 c++ 编译器不跟踪变量初始化。 在您的示例中, _id 存在于内存中(它有一个地址),但从未初始化。但是,由于编译器不跟踪,所以没有错误。

    【讨论】:

      【解决方案2】:

      它没有被构造,但是它的内存被分配了,因此 _id 存在并且持有一个未初始化的值。

      【讨论】:

        【解决方案3】:

        我无法理解这个问题。它之所以有效,是因为 c++ 标准允许这种行为。 类的内存此时已经分配,​​所以可以使用这个变量。

        【讨论】:

        • 我看不懂你看不懂问题
        【解决方案4】:

        想象一下,在您输入 : 以启动初始化程序列表的位置有一个不可见的 malloc。它会给你一个足够大的未初始化内存块来保存Derived 对象,包括Base 部分。编译器知道_id 所指的偏移量,因此它愿意为您提供存在于那里的垃圾值。

        在初始化列表中调用Base() 之后引用_id 是合法的。当基类构造函数还没有被调用时,编译器不会做特例。

        【讨论】:

          【解决方案5】:

          基类仍未构建,但我可以使用“_id”?

          不,您没有使用_id,因为还没有对象_id。但是有对象的原始内存,您可以使用标识符访问它,将原始内存解释为int 对象。

          Doing 会调用 Undefined Behavior,您最好不要这样做。未定义的行为可能会导致您的 HD 被格式化,您怀孕,或者程序看起来运行良好并执行它应该做的事情。而且你永远不知道它是哪一个,因为每个编译器、编译器版本、月相或诸如此类的东西都可能不同。

          在上述情况下,将原始内存解释为int 对象,常见的结果是该位置存在的任何位模式都被解释为整数并使用结果。但是,平台也可以捕获对未初始化内存的访问并引发硬件异常。
          如果 _id 是非 POD (std::string),则可能但不能保证的结果将是访问冲突。

          根据评论进行编辑:

          您可以在派生类的初始化列表中访问基类成员,甚至是未初始化的成员:

          #include <iostream>
          
          class Base{
          public:
              Base(int val):id_(val){};
          protected:
              int id_;
          };
          
          class Derived : Base {
          public:
              Derived(int val):Base(id_+val), blah_(id_) {};
              int blah() const {return blah_;}
          private:
              int blah_;
          };
          
          int main(){
              Derived d(60);
              std::cout << d.blah() << '\n';
              return 0;
          }
          

          【讨论】:

          • 好的,由于调用了基类构造函数,它尝试查找_id的范围是基类范围?如果我尝试在派生的初始化程序列表中访问 _id(没有显式调用基本 ctor),我会收到错误。
          • @tuco:语法在派生类的初始化列表中访问基类成员并没有错。看我的回答,我添加了一些编译得很好的代码。
          • 这很酷。我意识到我试图在派生的初始化列表中初始化基类成员并得到错误。
          • @tuco:一旦你通过了基类构造函数,使用基类成员是安全的。 在调用基类构造函数之前实际上可以使用它们,这是 C++ 语法的一个不需要的副作用,没有人费心去修复它。只有当你有虚拟基类时,你才能为不是 direct 基类或初始化列表中的数据成员的东西调用构造函数。
          【解决方案6】:

          如果你正确地声明了你的成员属性private,那将是一个错误。像这样将公共数据与继承混合可能只会导致混淆或不正确的行为,就像您观察到的那样。如果你的成员是私有的,编译器会防止这个错误,并增强你的类封装。

          编辑: _id 可用的原因是因为它的内存已经分配,​​它还没有被初始化。想一想:

          int x;
          int y = x;
          

          你不知道 y 中的内容是什么,因为 x 从未被初始化。

          【讨论】:

            猜你喜欢
            • 2016-10-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-03-30
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-05-11
            相关资源
            最近更新 更多