2011-05-11 124 views
4

在C++中,如果基類對象實例化爲未定義行爲作爲基礎對象,並隨後向下轉換爲派生對象?向下轉換基類型

當然,我會認爲它肯定是必須是未定義的行爲,因爲Derived類對象可能有基類沒有的成員變量。因此,如果類實例化爲基礎對象,則這些變量實際上不會存在,這意味着通過派生類指針訪問它們必須導致未定義行爲。

但是,如果Derived類僅提供額外的成員函數,但不包含任何其他成員數據呢?例如:

class Base 
{ 
    public: 
    int x; 
}; 

class Derived : public Base 
{ 
    public: 
    void foo();  
}; 

int main() 
{ 
    Base b; 
    Derived* d = static_cast<Derived*>(&b); 
    d->foo(); // <--- Is this undefined behavior? 
} 

此程序是否會導致未定義的行爲?

回答

7

是的,它仍然是未定義的行爲,因爲您正在向編譯器講述d的實際類型。

參見標準5.2.9/8:類型的「指針CV1 B」,

右邊的值,其中B是一個類型,可 轉換爲類型 「指針的右值如果從「指向 D」到「指向B的指針」的有效 標準轉換存在(4.10),則 cv2是與B的派生(第10小節)相同的等級 , ,或者 比cv資格更大,cv1和 B不是虛擬基類D. 空指針值(4.10)爲 轉換爲目標類型的空指針值 。如果 類型「指針CV1 B」點右值進行B ,實際上是類型d的 對象的子對象,將所得 指針指向類型D.的包圍對象 否則, 結果演員陣容不確定。

最後兩句話說,如果B指向指針實際上不是D派生類中的一部分,該轉換是不確定的行爲。

1

是的,這是完全未定義的行爲。這就是爲什麼當向下廣播時,除非你非常確定,否則你應該支持dynamic_cast

+2

請注意,在這個例子中,因爲沒有虛函數'dynamic_cast'將不起作用。 – 2011-05-11 17:13:47

4

C++ 03標準, 5.2.9.8勾畫出來(重點煤礦):

類型的「指針CV1 B」, 右邊的值,其中B是一個類型,可 轉換爲 類型的右值「指針CV2 D「,其中D是從B派生(第10條)的類別 ,如果存在從」指向 D「到」指向B的指針「的有效 標準轉換(4.10),則 cv2與, 或更大的cv-qualification比,cv1, 和B不是虛擬基類 D.空指針值(4。10)將 轉換爲目標類型的空指針值 。 如果 類型「指針CV1 B」點右值進行B ,實際上是類型d的 對象的子對象,將所得 指針指向類型D.的包圍對象 否則,結果 演員陣容未定義。

0

鑑於心理模型我有C++實現中的生成的機器代碼我說的術語,如果調用的方法是不虛擬和派生類不引入虛擬方法時基類現在沒有,並且多重繼承不涉及這個技巧,而且......並且它應該如你所期望的那樣工作,如果方法代碼確實只訪問在基礎對象中定義的成員。

但是,這仍然清楚地表明UB在C++中。

+0

那麼....它可能適用於一個非常小的情況 - 但它不一定會工作,如果你有多重繼承或多個繼承層等 – 2011-05-11 18:26:05

+0

是啊...任何不平凡的可能意味着基礎對象在派生中不在偏移0處。我編輯了我的回覆。 – 6502 2011-05-11 19:24:45