2012-05-01 50 views
3

心中已經問這些問題,前一段時間: Multiple inheritance casting from base class to different derived classC++運行時檢查,如果對象實現了接口

但我還是不知道我理解的答案。 現在的問題是:下面的代碼是否有效?

#include <iostream> 

using namespace std; 

struct Base 
{ 
    virtual void printName() 
    { 
     cout << "Base" << endl; 
    } 
}; 

struct Interface 
{ 
    virtual void foo() 
    { 
     cout << "Foo function" << endl; 
    } 
}; 

struct Derived : public Base, public Interface 
{ 
    virtual void printName() 
    { 
     cout << "Derived" << endl; 
    } 
}; 

int main(int argc, const char * argv[]) 
{ 
    Base *b = new Derived(); 
    Interface *i = dynamic_cast<Interface*>(b); 
    i->foo(); 

    return 0; 
} 

該代碼正常工作。但據我瞭解,根據上一個問題,它不應該。所以我不確定這樣的代碼是否有效。謝謝!

+0

您對上一個問題的回答中的註釋確實解釋了'dynamic_cast'將適用於您的案例。 – Chad

回答

4

它是有效的代碼。

爲什麼?
因爲dynamic_cast會告訴您所指向的對象是否實際上是要投射到的類型。
在這種情況下實際的對象被指向是類型Derived的類型和Derived的每個對象的類型是Interface(由於從InterfaceDerived繼承),因此dynamic_cast是有效的也和它的工作原理。

+0

與我以前的問題有什麼不同? (真的不明白) – Andrew

+0

@Andrew:沒有什麼區別,Emilio Garavaglia在上一個問題中給出了同樣的答案。 – interjay

+2

@Andrew:'dynamic_cast'只有在類中至少有一個'virtual'方法(又名多態類)時纔有效。見[this](http://stackoverflow.com/questions/4227328/faq-why-does-如果一個類至少有一個虛擬方法,則動態轉換隻能工作)。您的前一個示例沒有任何「虛擬」方法,因此無法使用「dynamic_cast」。 –

0

如果dynamic_cast成功,那麼它是有效的。它已經在運行時執行類型安全檢查。

+0

雖然在這種情況下情況確實如此,但我不喜歡設置「如果它有效,這是正確的」的先例。 – Chad

+0

,因爲它是'dynamic_cast',這就是論點。我不想重新解釋SO – UmNyobe

+0

@UmNyobe上十多個已知問題中出現的問題:OP所具有的問題是*它爲什麼有效?*答案不是因爲'dynamic_cast'這麼說。他已經知道'dynamic_cast'是這麼說的(OP提供了一個很好的示例代碼來演示它)真正的q是*爲什麼'dynamic_cast'有效?* –

2

只要涉及的類至少有一個虛擬方法(它可能是一個虛擬析構函數),那麼使用dynamic_cast就是正確的,並且可以用於一致性編譯器。

static_cast不同,dynamic_cast可以允許運行時檢查類型信息。但是,這也意味着它可能會失敗,並在使用它投擲指針時返回NULL。如果有可能不成功,應檢查演員結果。

在你問的前一個問題中,這些類沒有任何虛擬方法,因此不起作用,因爲dynamic_cast不能用於這樣的類。

0

考慮以下幾點:

Base *b = new B(); 
Interface *i = dynamic_cast<Interface *>(b); 

如若這項工作?號爲什麼,因爲BaseInterface彼此沒有關係。但是,在指向Base的指針指向也是從Interface派生的對象的特殊情況下,您可以投射(讀取:哄編譯器考慮該對象的類型爲InterfaceBase指針,並使用進一步運營商dynamic_cast

0

你的代碼是有效的,因爲標準是這樣說的5.2.7條第4款(C++ 2003標準):

運行時檢查邏輯的執行過程如下:

- 如果在大多數派生對象通過v,v點(引用)指向(引用)T對象的公共基類子對象,並且如果只有一個類型爲T的對象從指向(引用)的子對象派生v,結果是一個指向T對象的指針(左值)。否則,如果v指向(派生)大多數派生對象的公共基類子對象,並且最派生對象的類型具有T類型的基類,並且該派生類型是明確的且公有的,結果是一個指向最左派對象的T子對象的指針(左值)。

- 否則,運行時檢查失敗。

請注意在運行時檢查中使用「大多數派生對象」。在你的例子中,你的Base *b對象的「最派生對象」是一個Derived對象。由於類DerivedBaseInterface都公開繼承,所以在這種特定情況下,該對象可以轉換爲Interface*

相關問題