2012-07-14 24 views
8

也許我誤解繼承將如何在這裏工作,但這裏是我的問題:C++ - typeid的(),在派生類中使用不返回正確的類型

我有一個類選項,而一個類RoomOption是導出從中。我有另一個課室,裏面有一個shared_ptrs的矢量。主要我添加一個RoomOption到該矢量。然後,使用typeid()我檢查類型,它告訴我它的一個選項。從我讀過的,typeid應該返回派生類型,shared_ptrs不會導致切片,所以我不知道我做錯了什麼。

下面的代碼:

Room.h:

vector<shared_ptr<Option> > options; 
void addOption(shared_ptr<Option>); 
shared_ptr<Option> getOption(int); 

Room.cpp:

void Room::addOption(shared_ptr<Option> option){ 
    options.push_back(option); 
} 

shared_ptr<Option> Room::getOption(int i){ 
    return options[i]; 
} 

主:

shared_ptr<Room> outside(new Room(0, "", "")); 
outside->addOption(shared_ptr<RoomOption>(new RoomOption(0, "Go inside", hallway))); 
cout<<typeid(player->getRoom()->getOption(0)).name().get()<<endl; 
//This line prints "class std::tr1::shared_ptr<class Option> 

它發生,我認爲也許當添加或獲取選項Roo由於返回/參數類型,mOption作爲選項被鑄造。如果是這種情況,那麼我應該如何存儲多種類型的矢量?還是我得到這一切都錯了? = \

+3

您正在詢問共享指針的typeid。嘗試獲取共享指針所包含的事物的typeid。 – Mat 2012-07-14 13:10:49

+0

使用dynamic_cast檢查類型。除此之外,您獲取shared_ptr – Paranaix 2012-07-14 13:12:46

+0

的typeid返回選項* – 2012-07-14 13:13:55

回答

1

首先得到shared_ptr的typeid。

然後你應該使用dynamic_cast而不是typeid。例如:

if (dynamic_cast<RoomOption*>(player->getRoom()->getOption(0).get()) != 0){ 
    cout << "Its a RoomOption!" << endl; 
} 
+0

工作!感謝這個例子。找到一個簡單的例子來說明如何使用動態轉換來檢查類型O.o – 2012-07-14 13:20:35

+0

注意到dynmic_cast被認爲是一個非常昂貴的操作(因爲你的代碼需要查找RTTI信息)。因此,您不應該在時間敏感的代碼中頻繁使用它。 – Paranaix 2012-07-14 13:22:16

+0

已注意。謝謝=) – 2012-07-14 13:25:08

1

對象類型a shared_ptr<Option>指向的是它的值的一部分,而不是它的類型。因此,這行代碼被打破:

cout<<typeid(player->getRoom()->getOption(0)).name()<<endl; 

你想這樣的:

cout<<typeid(player->getRoom()->getOption(0).get()).name()<<endl; 

或許:

cout<<typeid(*(player->getRoom()->getOption(0))).name()<<endl; 

不會有什麼typeid告訴你的實際類型的東西,你通過到它。你通過了shared_ptr<Option>。它不會在對象內部查看它包含的內容。

+0

謝謝。儘管如此,仍然返回「Option *」。 – 2012-07-14 13:16:14

+0

好吧,現在取消引用那個指針,你就在那裏。 – 2012-07-14 13:16:49

14

typeid原理不同多態(用於具有至少一個虛擬函數的類)和非多態類型:

  • 如果類型是多態的,相應typeinfo結構其表示它在運行時確定(vtable指針通常用於此目的,但是這是一個實現細節)

  • 如果類型不是多態,則相應的typei NFO結構是在編譯時

在你的情況決定的,你確實有一個多態類Option,但shared_ptr<Option> itsef是不是多態的。它基本上是一個持有Option*的容器。在Optionshared_ptr<Option>之間絕對有沒有繼承關係。

如果你想獲得真正的類型,您首先需要使用Option* shared_ptr<Option>::get()來提取其容器的真正指針:

Option * myPtr = player->getRoom()->getOption(0).get(); 
cout << typeid(*myPtr).name(); << endl; 

或可替代(這是完全一樣的東西):

Option& myPtr = *player->getRoom()->getOption(0); 
cout << typeid(myPtr).name(); << endl; 
+0

我會刪除對vtable指針的引用,這是一個令人困惑的實現細節。 – 2012-07-14 14:47:49

+0

好我編輯! – 2012-07-14 15:45:54

+0

注意:您也可以直接使用'operator *'直接獲得對底層'Option'的引用,而不是先使用'get',然後在指針上使用'*'。 – 2012-07-14 15:48:12