I am making a simple console game in 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' ):
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->setI开发者_如何学Pythond(1);
cout << ply->getName() << endl;
cout << ply->getId() << endl;
delete ply;
}
How would I be able to call ply->setName etc?
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
:
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. Note that you can only use dynamic_cast
if the base class has at least one virtual function. 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 (i.e. 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
};
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.
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. In fact, by default, compilers often disable run-time type information (RTTI), which is needed to make dynamic_cast work.
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.
精彩评论