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]->lives 时,我无法这样做。这是我得到的错误:

error C2039: 'lives' : is not a member of 'BaseObj'
4

5 回答 5

4

myObjs 是一个指向 base 的指针,因此它只能访问 base 成员

于 2011-02-05T07:31:39.323 回答
3

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

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

  1. dynamic_cast<PlayerObj*>(p)

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

    为了能够用于基->派生转换,如果默认情况下编译器没有启用运行时类型信息 (RTTI)dynamic_cast ,并且您的基类是“多态类型”,您必须确保它已启用,即它必须至少有一个虚拟方法。

  2. static_cast<PlayerObj*>(p)

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

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

于 2011-02-05T08:19:24.637 回答
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;
}
于 2011-02-05T08:15:29.950 回答
1

你可以这样做:

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

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

(static_cast<PlayerObj*>(myObjs[2]))->lives = ...
于 2011-02-05T07:58:08.127 回答
1

哇,非常感谢大家的快速回复!只是跳回去让大家知道您帮助我解决了问题,现在一切正常。

我和

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

并将对象类型枚举添加到基类以定义类型。

于 2011-02-05T09:07:14.800 回答