2015-04-18 130 views
2

我會嘗試檢查一個指針作爲參數如下傳遞什麼類型:如何在運行時檢查類型?

#include <iostream> 
struct A{}; 
struct B:A{}; 
struct C:A{}; 
C *c = new C; 
B *b = new B; 
A *a = new A; 
void foo (A *a) 
{ 
    if(dynamic_cast<B*>(a)) 
    { 
     std::cout << "Type is B*" << std::endl; 
    //cannot dynamic_cast 'a' (of type 'struct A*') to type 'struct B*' (source type is not polymorphic) 
    } 

    if(dynamic_cast<C*>(a)) 
    { 
     std::cout << "Type is C*" << std::endl; 
     //cannot dynamic_cast 'a' (of type 'struct A*') to type 'struct C*' (source type is not polymorphic) 
    } 
} 

但甚至不進行編譯。有可能這樣做嗎?我的意思是,確定什麼指針指向我們作爲函數參數傳遞的類型?

+2

「A」中至少需要一個'virtual'函數,最簡單的是聲明一個虛擬析構函數。 –

+0

@πάνταῥεῖ用於什麼?虛擬函數如何幫助我在運行時確定類型?沒有看到...... –

+0

編譯器在這種情況下創建了一個vtable,這對'dynamic_cast'是必需的。 –

回答

1

你需要改變A的定義至少需添加一個虛擬功能。簡單的解決方法:添加虛擬析構函數:

struct A 
{ 
    virtual ~A() {} 
}; 

然後:

int main() 
{ 
    foo(b); 
    foo(c); 
    return 0; 
} 

輸出:

Type is B* 
Type is C* 

這裏試試:link

呵呵,我知道,這只是一個示例代碼,但是這些用new創建的全局變量看起來很糟糕。

+0

注意:如果派生類具有自己的資源,則虛擬析構函數是件好事。它確保在刪除基類指針時正確銷燬派生類。 –

+0

我完全知道,虛擬析構函數的目的是什麼,所以有什麼意義?即使我們添加虛擬成員函數,我們也很可能將析構函數聲明爲virtual *,因爲這是非常普遍的做法。 –