samedi 19 avril 2014

c ++ - appel à une fonction spécifique à l'objet sur un vecteur STL d'objets polymorphes - Stack Overflow


So I have a class hierarchy that essentially has Entity class as the parent abstract class and a bunch of other classes that derive from it, such as Door, Player, Ground, etc.


I also have a three-dimensional vector that stores the pointers to objects of type Entity and I fill up this vector with the derived objects. Within the Door class I have a method called isOpen() that simply returns a bool. This function is specific to the Door class and is neither found in Entity class nor in any other derivations of it (as I don't need to check whether, for example, a Ground object is open or not).


Now, knowing that there exists an object of type Door at vector position i, j, k, I would like to call the method isOpen like so: vector[i][j][k]->isOpen(). Unfortunately, when I do this, the compiler returns class Entity has no member named isOpen(). This is understandable since the function isOpen() is exclusive to the Door class, but what can I do in order to make this sort of call possible?




One way to solve this is with a down cast to a Door * first. However, in order for this down cast to be type safe, you should use dynamic_cast<Door *>(). If Entity does not already have a virtual method, you can add a virtual destructor.


class Entity {
//...
virtual ~Entity () {}
};

void foo (Entity *e) {
//...
Door *door = dynamic_cast<Door *>(e);
if (door) {
if (door->isOpen()) {
//...
}
}
//...
}



Short answer:


Cast the Entity down to a door: static_cast<Door*>(vector[i][j][k])->isOpen().


Long answer:


Your design isn't proper if you need to know a specific derived type is at a specific location. Fixing this might be as simple as moving the isOpen() function up to Entity with a default implementation returning true. Or it could require a whole rethinking of the code that works with the members of vector.




Consider polymorphic casting as supported by the language using dynamic_cast<> For references it will throw an exception (std::bad_cast) but for pointers if the target type is not compatible it will simply return NULL, so... assuming your base class and its derivations are indeed polymorphic (i.e. at least one virtual method):


Door* pDoor = dynamic_cast<Door*>(vector[i][j][k]);
if (pDoor)
pDoor->isOpen();

Comments about the design withheld. Opinions are like... yeah. everyone has one.



So I have a class hierarchy that essentially has Entity class as the parent abstract class and a bunch of other classes that derive from it, such as Door, Player, Ground, etc.


I also have a three-dimensional vector that stores the pointers to objects of type Entity and I fill up this vector with the derived objects. Within the Door class I have a method called isOpen() that simply returns a bool. This function is specific to the Door class and is neither found in Entity class nor in any other derivations of it (as I don't need to check whether, for example, a Ground object is open or not).


Now, knowing that there exists an object of type Door at vector position i, j, k, I would like to call the method isOpen like so: vector[i][j][k]->isOpen(). Unfortunately, when I do this, the compiler returns class Entity has no member named isOpen(). This is understandable since the function isOpen() is exclusive to the Door class, but what can I do in order to make this sort of call possible?



One way to solve this is with a down cast to a Door * first. However, in order for this down cast to be type safe, you should use dynamic_cast<Door *>(). If Entity does not already have a virtual method, you can add a virtual destructor.


class Entity {
//...
virtual ~Entity () {}
};

void foo (Entity *e) {
//...
Door *door = dynamic_cast<Door *>(e);
if (door) {
if (door->isOpen()) {
//...
}
}
//...
}


Short answer:


Cast the Entity down to a door: static_cast<Door*>(vector[i][j][k])->isOpen().


Long answer:


Your design isn't proper if you need to know a specific derived type is at a specific location. Fixing this might be as simple as moving the isOpen() function up to Entity with a default implementation returning true. Or it could require a whole rethinking of the code that works with the members of vector.



Consider polymorphic casting as supported by the language using dynamic_cast<> For references it will throw an exception (std::bad_cast) but for pointers if the target type is not compatible it will simply return NULL, so... assuming your base class and its derivations are indeed polymorphic (i.e. at least one virtual method):


Door* pDoor = dynamic_cast<Door*>(vector[i][j][k]);
if (pDoor)
pDoor->isOpen();

Comments about the design withheld. Opinions are like... yeah. everyone has one.


0 commentaires:

Enregistrer un commentaire