访问数组中派生类的问题

时间:2011-02-05 07:24:52

标签: c++ derived-class

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'

5 个答案:

答案 0 :(得分:4)

答案 1 :(得分:3)

C ++是一种静态类型语言,这意味着每个变量都有一个特定的类型。您的数组包含指向BaseObj的指针,这意味着编译器只允许访问该类中定义的成员。

您可以告诉编译器确实其中一个指针以两种方式指向更具体(即派生)的类实例:

  1. dynamic_cast<PlayerObj*>(p)

    如果确实PlayerObj指向该类的实例(或从p派生的类的实例),则此表达式将返回指向PlayerObj的指针。如果不是这种情况,则即使p不为空,返回的指针也将是空指针。

    为了能够使用dynamic_cast进行base-gt;派生转换,如果编译器默认情况下没有为Run-Time Type Information (RTTI)设置并且您的基类是“多态类型”,即它必须至少有一个虚方法。

  2. static_cast<PlayerObj*>(p)

    这会进行相同的转换,但是如果p未指向PlayerObj的实例或从PlayerObj派生的类,那么您将进入“未定义的行为”,就像你写出一个数组或在delete之后使用一个对象一样。这可能意味着程序崩溃,疯狂的行为,从你的鼻子飞出的守护进程甚至更糟(例如,一切似乎都在工作,并且崩溃将在以后发生一百万次执行的指示)。

  3. 在许多C ++程序中使用的解决方案通常仅使用static_cast,但最终通过在基类中具有“类型”数据成员(例如枚举)来首先检查指向实例的类型。这意味着您基本上构建自己的RTTI而不是使用编译器提供的RTTI。

答案 2 :(得分: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;
}

答案 3 :(得分:1)

你可以这样做:

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

或者如果您确定myObjs [2]的类型为PlayerObj *,您可以使用:

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

答案 4 :(得分:1)

哇,非常感谢你们的快速回复!回过头来让大家知道你帮助我解决问题,现在一切都运转良好。

我去了

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

并在基类中添加了一个对象类型枚举来定义类型。