2011-02-05 141 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; 
} 

和添加的对象类型枚举的基类来定义的类型。