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'?
感谢
答案 0 :(得分:2)
一个更简单的例子:int x = x + 1;
向您展示c ++编译器不跟踪变量初始化。
在您的示例中,_id存在于内存中(它有一个地址),但从未初始化。但是,由于编译器没有跟踪,因此没有错误。
答案 1 :(得分:1)
它没有被构建,但是它的内存被分配,因此_id存在并保持未初始化的值。
答案 2 :(得分:0)
我无法理解这个问题。它的工作原理是因为c ++标准允许这种行为。 此时已经分配了类的内存,因此可以使用此变量。
答案 3 :(得分:0)
基类仍未构建,但我可以使用'_id'?
不,您没有使用_id
,因为还没有对象_id
。但是存在对象的原始内存,您可以使用标识符访问它,将原始内存解释为int
对象。
执行调用 未定义的行为 ,您最好不要这样做。未定义的行为可能会导致您的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;
}
答案 4 :(得分:0)
想象一下,在您键入malloc
以启动初始值设定项列表时,有一个不可见的:
。它会给你一个未初始化的内存块,其大小足以容纳Derived
对象,包括Base
部分。编译器知道_id
引用的偏移量,因此它愿意为您提供生活在那里的垃圾值。
在初始化列表中调用_id
后引用Base()
是合法的。编译器没有为基类构造函数尚未调用时提供特殊情况。
答案 5 :(得分:0)
如果您正确声明了您的成员属性private
,那将是一个错误。将公共数据与这样的继承混合可能只会导致您观察到的混乱或不正确的行为。如果你的成员是私有的,编译器会阻止这个错误,它会增强你的类封装。
编辑:_id可用的原因是因为它的内存已经分配,它还没有被初始化。想一想以下几点:
int x;
int y = x;
你不知道y中会有什么因为x从未被初始化。