使用基类指针访问派生类成员

6

我正在使用C++制作一个简单的控制台游戏。

我想知道在使用指向基类(“Entity”)的指针时,是否可以访问“entPlayer”类的成员:

class Entity {
public:
    void setId(int id) { Id = id; }
    int getId() { return Id; }
protected:
    int Id;
};

class entPlayer : public Entity {
    string Name;
public:
    void setName(string name) { Name = name; }
    string getName() { return Name; }
};

Entity *createEntity(string Type) {
    Entity *Ent = NULL;
    if (Type == "player") {
        Ent = new entPlayer;
    }
    return Ent;
}

void main() {
    Entity *ply = createEntity("player");
    ply->setName("Test");
    ply->setId(1);

    cout << ply->getName() << endl;
    cout << ply->getId() << endl;

    delete ply;
}

我该如何调用ply->setName等方法?
或者
如果这种方式不可行,有更好的方法吗?

1
抱歉,我必须编辑您的代码格式。空白行使您的代码变得非常长!关于您的代码还有一个小建议:保持一致的命名约定,例如所有类名都像这样AllClassNamesLikeThis,参数名称也应该像这样parameter_names_like_this。另外一个问题是:你以后会因为缩写词像“ent”而自责的。我真的无法理解什么是entPlayer。我认为你的意思只是“Player”,或者如果你觉得详细一些,可以用“PlayerEntity”。 - allyourcode
4个回答

12

可以使用类型转换实现。如果你确定基类指针指向派生类的对象,你可以使用static_cast

Entity* e = /* a pointer to an entPlayer object */;
entPlayer* p = static_cast<entPlayer*>(e);
p->setName("Test");

如果您不确定,那么您需要使用dynamic_cast并测试结果以确保它不为空。请注意,只有在基类至少有一个虚函数时才能使用dynamic_cast。示例:

Entity* e = /* a pointer to some entity */;
entPlayer* p = dynamic_cast<entPlayer*>(e);
if (p)
{
    p->setName("Test");
}

话虽如此,更好的做法是使用多态性(encapsulate your class's functionality using polymorphism,即虚函数)来封装你的类的功能。

说到虚函数,你所实现的类层次结构具有未定义的行为:如果基类没有虚析构函数,那么只能通过指向其基类之一的指针删除派生类型的对象。因此,您需要向基类添加虚析构函数。


我有一个相关的问题,这个答案回答了我的问题:D 我想知道的是“如何判断我的基本指针是否真正指向派生对象?”。我从中得到的答案是使用dynamic_cast(仅在基类具有虚函数时有效),然后查看结果是否为NULL。#胜利宝贝 - allyourcode
这也(部分地)回答了我长期以来对C ++的另一个问题:各种类型的强制转换之间有什么区别?它们似乎有相当多! - allyourcode

1
我会考虑做这样的事情:
public:
void setId(int id) 
{

    Id = id;

}

void virtual setName( string name ) = 0; // Virtual Function 
string virtual getName() = 0; // Virtual Function

int getId() { return Id; }

protected:
    int Id;

};

class entPlayer : public Entity {

    string Name;

public:
    entPlayer() {

        Name = "";
        Id = 0;

    }

    void entPlayer::setName(string name) {  // Must define function

        Name = name;
}

string entPlayer::getName() { return Name; } // again must define function here

};

0

你可以进行动态转换:

entPlayer * pPlayer = dynamic_cast<entPlayer *>(pointer_to_base);

如果成功,这将导致一个派生指针。

否则将返回NULL


0

C++会让你想做的事情变得非常困难,因为这可能不是你应该做的事情,而它试图引导你去进行良好的面向对象设计。事实上,默认情况下,编译器经常禁用运行时类型信息(RTTI),这对于使dynamic_cast工作是必要的。

如果不知道你的更广泛的背景,很难说你应该做什么。我可以说的是,如果你想要一个更具体的指针,你应该给它带上戒指你几乎肯定不应该使用返回一个Entity*的函数,并且可能有更好的方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接