我知道在基類的構造函數中 - 調用虛方法時 - 調用基方法,而不是派生 - 請參閱Calling virtual functions inside constructors。這是否正確:在構造Base對象之前調用Derived的虛方法?
我的問題與此主題有關。我只是想知道如果我在Derived類的構造函數中調用virtual方法會發生什麼 - 但是在構造Base部分之前。我的意思是打電話來評估基類構造函數參數的虛方法,見代碼:
class Base {
public:
Base(const char* name) : name(name) {
cout << "Base():" << name << endl;
}
virtual const char* getName() {
cout << "Base::getName()" << endl;
return "Base";
}
protected:
const char* name;
};
class Derived : public Base {
public:
Derived() : Base(getName()) {
cout << "Derived():" << name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return "Derived";
}
};
int main() {
Derived d;
}
編譯器G ++(版本4.3.x-4.5X版本)輸出爲:
Derived::getName()
Base():Derived
Derived():Derived
不過我期望:
Base::getName()
Base():Base
Derived():Base
這不會看錯了 - 但考慮到這個例子,它產生segmentation fault
:
class Derived : public Base {
public:
Derived() : Base(getName()), name(new string("Derived")) {
cout << "Derived():" << Base::name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return name->c_str();
}
private:
string* name;
};
請問這是正確的g ++行爲嗎? C++標準對此有何評論?也許這是未定義的行爲?
[UPDATE1] 我考慮到羅伯特和奧利的答案 - 我改變了我的第一個例子。然後getName()被稱爲「虛擬」 - 它會產生分段錯誤。請回答我的問題到這個部分。
const char* virtualGetName(Base* basePtr)
{
return basePtr->getName();
}
class Derived : public Base {
public:
Derived() : Base(virtualGetName(this)) {
cout << "Derived():" << Base::name << endl;
}
virtual const char* getName() {
cout << "Derived::getName()" << endl;
return "Derived";
}
};
我在我的問題中添加了更新,我相信更多的不像您的回答 - 但現在我真的不知道爲什麼在最後一個示例中出現了「段錯誤」。似乎並不總是方法被虛擬調用。並且vpointer到Derived :: vtable被設置在ctor體的開始處(在{之後)。 – PiotrNycz
我已經更新了我的答案。我前兩次嘗試解釋這種行爲是災難性的失敗。我相當有信心,這個最新的解釋是正確的:-)。 –
@PiotrNycz:「爲什麼分段錯誤?」行爲是未定義的。分段錯誤是[但一個可能的結果](http://stackoverflow.com/a/1553407/140719)調用未定義的行爲。 – sbi