C ++ inheritance multiple d’inheritance

J’ai un cours:

class Base; 

J’ai aussi une interface

 class Interface; 

Ensuite, je crée une classe

 class Derived : public Base, public Interface; 

Si j’ai Base *object = new Derived;

Comment puis-je atsortingbuer un object à Interface ? (bien sûr si je sais que l’object est en fait une classe dérivée)

MODIFIER:

J’ai essayé dynamic_cast et static_cast (non compilé). Alors laissez-moi expliquer le problème un peu plus:

J’ai:

 class Object {...} class ITouchResponder { public: virtual bool onTouchBegan(XTouch *touch) = 0; virtual void onTouchMoved(XTouch *touch) = 0; virtual void onTouchEnded(XTouch *touch) = 0; }; class Ball : public Object, public ITouchResponder {...}; class TentacleSensor : public Object, public ITouchResponder {...} 

Les objects ont une propriété bool touchable_ . Si c’est vrai, l’object implémente l’interface ITouchResponder.

Quand je l’utilise:

 bool Level::onTouchBegan(XTouch *touch) { ... ITouchResponder *responder = callback.nearestTouchable(); if (responder) { if (responder->onTouchBegan(touch)) { if (responder != ball_) { touch->setUserData(responder); } } } return true; } ITouchResponder *QueryCallback::nearestTouchable() const { for (list::const_iterator it = objects_.begin(); it != objects_.end(); ++it) { if ( (*it)->isTouchable() ) return (*it)->asTouchResponder(); } return 0; } 

asTouchResponder est une méthode d’ Object :

  ITouchResponder * Object::asTouchResponder() { assert(touchable_); ITouchResponder *res = dynamic_cast(this); assert(res); return res; } 

J’ai un mauvais excès d’erreur dans xcode.

Mais si je fais l’ Object : public ITouchResponder tout fonctionne bien. Qu’est-ce que je fais mal ?

Classe d’object complète:

 class Object// : public ITouchResponder { public: struct Def { Def() { level = 0; world = 0; touchable = false; acceptsContacts = false; body = 0; node = 0; } Level *level; b2World *world; bool touchable; bool acceptsContacts; b2Body *body; XNode *node; }; Object(const Def &def); virtual ~Object(); virtual void update(float dt); bool isTouchable() const {return touchable_;} void addDependantObject(Object *object); void removeDependantObject(Object *object); virtual void objectWillBeRemoved(Object *object) {} //this function is automatically called to every dependant object when object is removed virtual XVec2 position() const; virtual float rotation() const; bool acceptsContacts() const {return acceptsContacts_;} b2Body *body() const {return body_;} Level *level() const {return level_;} b2World *world() const {return world_;} ITouchResponder *asTouchResponder(); /* virtual bool onTouchBegan(XTouch *touch) { return false; } virtual void onTouchMoved(XTouch *touch) { } virtual void onTouchEnded(XTouch *touch) { }*/ protected: Level *level_; b2World *world_; bool touchable_; bool acceptsContacts_; XNode *node_; b2Body *body_; list dependantObjects_; }; 

Si Base a virtual fonction virtual (même s’il s’agit d’ virtual destructeur virtual ), alors:

 Derived *pDerived = dynamic_cast(object); 

Sinon, utilisez

 Derived *pDerived = static_cast(object); 

Notez que si Base n’a pas de fonction virtuelle, dynamic_cast ne sera pas compilé. Dans dynamic_cast , seule la source doit être un object polymorphe pour pouvoir être compilée et si la destination n’est pas polymorphe, alors dynamic_cast renverra un pointeur null:

Supposons que A et B sont de type polymorphe et que C n’est pas polymorphe, alors

 A *pA = dynamic_cast(new C()); //error - source is not polymorphic! A *pA = dynamic_cast(new B()); //ok if ( pA == 0 ) cout << "pA will be null if B is not derived from A" << endl; C *pC = dynamic_cast(new B()); //ok if ( pC == 0 ) cout << "pC must be null" << endl; 

Si vous savez avec certitude que l’object appartient à la classe Derived , utilisez static_cast , sinon, utilisez dynamic_cast et vérifiez le résultat.

Vous pouvez utiliser dynamic_cast(object) pour cela, et si la dissortingbution réussit, vous obtiendrez un Derived* , sinon la dissortingbution retournera NULL. Vous utilisez ce type de conversion si Base est un type polymorphe, c’est-à-dire. contient une fonction virtuelle, et si ce n’est pas le cas, vous pouvez utiliser static_cast un static_cast .

Votre problème est que vous avez une classe Object qui n’hérite pas de votre interface ITouchResponder et que, par conséquent, votre dynamic_cast d’ Object vers votre interface n’est pas valide. Vous ne pouvez effectuer une dynamic_cast que sur des classes qui héritent les unes des autres, c’est tout le but du polymorphism. Ainsi, comme vous l’avez suggéré dans votre exemple, votre classe Object doit hériter publiquement de votre interface.

ITouchResponder *res = dynamic_cast(this); de Derived à Base Interface, mais votre Derived ne dérive pas vraiment de votre interface, c’est pourquoi il ne fonctionne pas.

Il y a plusieurs façons mais elles n’ont pas le même impact:

 Derived* derived = static_cast(object); 

Utilisez celui-ci si vous savez au moment de la compilation qu’il devrait être du type correct. Cela n’échouera pas à l’exécution si ce n’est pas possible, mais le sera à la compilation.

 Derived* derived = dynamic_cast(object); 

Utilisez cette option si vous n’êtes pas sûr et si vous voulez que le moteur d’exécution vérifie automatiquement si cela est possible. Si c’est le cas, vous obtiendrez un pointeur valide, sinon, vous obtiendrez un nullptr. Sachez que les vérifications dynamic_cast <> coûtent cher en temps d’exécution. Par conséquent, de nombreuses personnes utilisent parfois des conteneurs associatifs avec des pointeurs type_info comme clés, car la vérification est moins coûteuse, mais cela dépend vraiment du contexte. Pour obtenir plus d’informations, recherchez le mot-clé typeid.

Maintenant, il y a aussi la façon de faire en C, mais ce n’est pas recommandé car on ne sait pas exactement ce que le compilateur va générer. Au moins, avec ces méthodes précédentes, vous savez exactement comment le code doit se comporter. Donc je ne vais pas le décrire.