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'?繼承,調用基類ctors
感謝
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'?繼承,調用基類ctors
感謝
這不是建造,但其分配內存,因此存在_id並持有未初始化值。
我不明白這個問題。它的工作原理是因爲C++標準允許這種行爲。 這個類的內存已經被分配了,所以可以使用這個變量。
一個更簡單的例子:int x = x + 1;
告訴你,C++編譯器不跟蹤變量初始化。 在你的例子中,_id存在於內存中(它有一個地址),但從未初始化。但是,由於編譯器沒有跟蹤,所以沒有錯誤。
基類仍然沒有構建,但我可以使用'_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;
}
想象有在您輸入:
以啓動初始化程序列表的位置看不到malloc
。它會給你一個未初始化的內存塊,足以容納一個Derived
對象,包括Base
部分。編譯器知道_id
所指的偏移量,所以它會隨心所欲地爲您提供生活在那裏的垃圾值。
在初始化程序列表中調用Base()
之後引用_id
是合法的。當基類構造函數尚未被調用時,編譯器不會做出特殊情況。
如果您正確聲明瞭您的成員屬性private
,那將是一個錯誤。像這樣將公有數據與繼承混合在一起可能只會導致混淆或不正確的行爲,例如你所觀察到的。如果你的成員是私有的,那麼編譯器會防止這個錯誤,並增強你的類封裝。
編輯:_id可用的原因是因爲它的內存已被分配,它只是還沒有被初始化。想一些沿線:
int x;
int y = x;
你不知道什麼將在y因爲x從未初始化。
我不明白你不明白問題 – stijn 2010-07-22 12:14:58