简体   繁体   English

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

[英]Accessing derived class members with a base class pointer

I am making a simple console game in C++ 我正在用C ++制作一个简单的控制台游戏

I would like to know if I can access members from the 'entPlayer' class while using a pointer that is pointing to the base class ( 'Entity' ): 我想知道我是否可以在使用指向基类('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;
}

How would I be able to call ply->setName etc? 我怎么能调用ply-> setName等?

OR 要么

If it's not possible that way, what would be a better way? 如果这种方式不可能,那会是更好的方法吗?

It is possible by using a cast. 可以通过使用演员表。 If you know for a fact that the base class pointer points to an object of the derived class, you can use static_cast : 如果您知道基类指针指向派生类的对象这一事实,则可以使用static_cast

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

If you don't know for sure, then you need to use dynamic_cast and test the result to see that it is not null. 如果您不确定,那么您需要使用dynamic_cast并测试结果以查看它不是null。 Note that you can only use dynamic_cast if the base class has at least one virtual function. 请注意,如果基类至少有一个虚函数,则只能使用dynamic_cast An example: 一个例子:

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

That said, it would be far better to encapsulate your class's functionality using polymorphism (ie virtual functions). 也就是说,使用多态(即虚函数)封装类的功能会好得多。

Speaking of virtual functions, your class hierarchy as implement has undefined behavior: you can only delete an object of a derived type through a pointer to one of its base classes if the base class as a virtual destructor. 说到虚函数,作为实现的类层次结构具有未定义的行为:如果基类作为虚拟析构函数,则只能通过指向其基类之一的指针来删除派生类型的对象。 So, you need to add a virtual destructor to the base class. 因此,您需要向基类添加虚拟析构函数。

I would consider doing something like this: 我会考虑做这样的事情:

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

};

C++ makes what you are trying to do really awkward, because this is probably not what you should be doing, and it is trying to lead you to good object-oriented design. C ++使你想要做的事情变得非常尴尬,因为这可能不是你应该做的,它试图引导你进行良好的面向对象设计。 In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work. 实际上,默认情况下, 编译器通常会禁用运行时类型信息 (RTTI),这是使dynamic_cast工作所必需的。

Without knowing your broader context, it's hard to say what you should do instead. 如果不了解更广泛的背景,很难说你应该做些什么。 What I can say is that if you wanted a more specific pointer, you should have put a ring on it you almost certainly shouldn't use a function that returns an Entity* , and there is probably a better approach. 我可以说的是,如果你想要一个更具体的指针, 你应该在它上面放一个戒指, 你几乎肯定不应该使用一个返回Entity*的函数,并且可能有更好的方法。

You can do a dynamic cast: 你可以做一个动态演员:

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

This will (if successful) result in a derived pointer. 这将(如果成功)导致派生指针。

Otherwise NULL is returned. 否则返回NULL

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM