2011-02-05 102 views
1
class BaseObj 
{ 
public: 
    int position; 
}; 

class EnemyObj: public BaseObj 
{ 
public: 
    int quantity; 
}; 

class PlayerObj: public BaseObj 
{ 
public: 
    int lives; 
}; 

int main() 
{ 
    BaseObj* myObjs[3]; 

    BaseObj* b = new BaseObj(); 
    b->position = 1; 
    myObjs[0] = b; 

    EnemyObj* e = new EnemyObj(); 
    e->position = 2; 
    e->quantity = 5; 
    myObjs[1] = e; 

    PlayerObj* p = new PlayerObj(); 
    p->position = 3; 
    p->lives = 2; 
    myObjs[2] = p; 

    myObjs[2]->lives = 2; // error is here 
    return 0; 
} 

我的問題是,我想有我所有的遊戲對象的數組,所以我可以把它們都在一起,但是當我嘗試訪問 myObjs [2] - >生活 我無法這樣做。這是我的錯誤:問題訪問派生類在陣列

error C2039: 'lives' : is not a member of 'BaseObj' 
+0

你不應該真的多態地使用數組。你最好使用std :: vector。一個相當好的解釋,爲什麼可以在這裏找到http://stackoverflow.com/questions/1043402/why-this-code-crashes – 2011-02-05 08:56:26

回答

3

C++是一種靜態類型語言,這意味着每個變量都有一個特定的類型。您的數組包含指向BaseObj的指針,這意味着編譯器將只允許訪問該類中定義的成員。

你可以告訴那些指針確實一個指向更具體的(即派生)類實例有兩種方式編譯:

  1. dynamic_cast<PlayerObj*>(p)

    這個表達式將返回一個指向PlayerObj如果確實p指向該類的實例(或從PlayerObj派生的類的實例)。如果不是這種情況,即使p不爲空,返回的指針也是空指針。

    爲了能夠使用dynamic_cast的基極 - >導出轉換必須確保,如果它不是在默認情況下爲你的編譯器和基類是「多態型」 elabled Run-Time Type Information (RTTI)已啓用,也就是它必須至少有一個虛擬方法。

  2. static_cast<PlayerObj*>(p)

    這做同樣的轉換,但是如果p沒有指向的PlayerObjPlayerObj,那麼你進入「未定義行爲」土地派生的類的實例,當你寫一模一樣在數組之外或在使用對象之後使用delete d。這可能意味着程序崩潰,瘋狂行爲,守護進程從你的鼻子飛出,甚至更糟糕(例如,無論如何,一切似乎都有效,而且崩潰將在一百萬次執行後發生)。

經常在許多C++程序中使用的一個解決方案是隻使用static_cast但最終由具有在基類「類型」的數據成員(例如枚舉)檢查第一所指向的實例的類型。這意味着你基本上構建自己的RTTI而不是使用編譯器提供的RTTI。

1

你可以這樣做:

PlayerObj* player = dynamic_cast<PlayerObj*>(myObjs[2]); 
if(player) 
{ 
    player->lives = ... 
} 

,或者如果你確信myObjs [2]的類型是PlayerObj的*您可以使用:

(static_cast<PlayerObj*>(myObjs[2]))->lives = ... 
+0

+1但可能第一種方法更好,因爲該數組包含所有類型的對象似乎。 – 2011-02-05 07:58:58

+0

-1..`dynamic_cast`不能應用於非多態類型。 http://www.ideone.com/tsqRO – Nawaz 2011-02-05 08:44:53

2

dynamic_cast是你的朋友:

#include <iostream> 
#include <memory> 

class BaseObj { 
public: 
    BaseObj() : position(-1) { 
    } 

    virtual ~BaseObj() { 
    } 

    int position; 
}; 

class EnemyObj : public BaseObj { 
public: 
    EnemyObj() : quantity(0) { 
    } 

    virtual ~EnemyObj() { 
    } 

    int quantity; 
}; 

class PlayerObj : public BaseObj { 
public: 
    PlayerObj() : lives(9) { 
    } 

    virtual ~PlayerObj() { 
    } 

    int lives; 
}; 

int main() { 
    BaseObj* myObjs[3]; 

    BaseObj* b = new BaseObj(); 

    b->position = 1; 
    myObjs[0] = b; 

    EnemyObj* e = new EnemyObj(); 
    e->position = 2; 
    e->quantity = 5; 
    myObjs[1] = e; 

    PlayerObj* p = new PlayerObj(); 
    p->position = 3; 
    p->lives = 2; 
    myObjs[2] = p; 

    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[0])) { 
     std::cout << player << "\n"; 
     player->lives = 2; 
    } 
    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[1])) { 
     std::cout << player << "\n"; 
     player->lives = 2; 
    } 
    if (PlayerObj * const player = dynamic_cast<PlayerObj*>(myObjs[2])) { 
     std::cout << player << "\n"; 
     player->lives = 2; 
    } 

    return 0; 
} 
1

哇,非常感謝你的回覆!回過頭來讓大家都知道你幫助我解決了這個問題,現在它完美地工作了。

我去

if(myObjs[2].type == PlayerObj) 
{ 
     (static_cast <PlayerObj*>(myObjs[2]))->lives = 0; 
} 

和添加的對象類型枚舉的基類來定義的類型。