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 :(得分:4)
答案 1 :(得分:3)
C ++是一种静态类型语言,这意味着每个变量都有一个特定的类型。您的数组包含指向BaseObj
的指针,这意味着编译器只允许访问该类中定义的成员。
您可以告诉编译器确实其中一个指针以两种方式指向更具体(即派生)的类实例:
dynamic_cast<PlayerObj*>(p)
如果确实PlayerObj
指向该类的实例(或从p
派生的类的实例),则此表达式将返回指向PlayerObj
的指针。如果不是这种情况,则即使p
不为空,返回的指针也将是空指针。
为了能够使用dynamic_cast
进行base-gt;派生转换,如果编译器默认情况下没有为Run-Time Type Information (RTTI)设置并且您的基类是“多态类型”,即它必须至少有一个虚方法。
static_cast<PlayerObj*>(p)
这会进行相同的转换,但是如果p
未指向PlayerObj
的实例或从PlayerObj
派生的类,那么您将进入“未定义的行为”,就像你写出一个数组或在delete
之后使用一个对象一样。这可能意味着程序崩溃,疯狂的行为,从你的鼻子飞出的守护进程甚至更糟(例如,一切似乎都在工作,并且崩溃将在以后发生一百万次执行的指示)。
在许多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;
}
并在基类中添加了一个对象类型枚举来定义类型。