Accéder à «ce» pointeur de la classe concrète à partir de l’interface

Après avoir écrit un test, j’ai déterminé que le pointeur this dans une interface n’était pas égal au pointeur this de la classe concrete, ce qui signifie que je ne peux pas simplement utiliser un transtypage de style C.

 class AbstractBase {...}; class AnInterface { public: AnInterface() {...} // need AbstractBase * here ~virtual AnInterface() {...} // and here }; class Concrete : public AbstractBase, public AnInterface {}; 

Mon interface a besoin d’un pointeur de classe de base sur la classe concrète qui en hérite dans le constructeur et le destructeur afin de gérer l’enregistrement et la désinscription liés à l’interface.

Chaque object concret qui hérite de l’interface doit d’abord hériter de la classe de base abstraite, il est toujours le premier dans la présentation.

Pour le constructeur, ce n’est pas si difficile, je peux append un pointeur dans le constructeur de l’interface et le transmettre à partir de la classe concrète. Mais le destructeur n’a pas de paramètre, alors je suis dans le noir là-bas.

Les solutions que j’ai proposées jusqu’à présent viennent avec des frais généraux:

1 – stocke le pointeur dans l’interface à utiliser dans le destructeur – ajoute à un pointeur une surcharge de mémoire

 class AnInterface { public: AnInterface(AbstractBase * ap) {...} ~virtual AnInterface() {...} // and here private: AbstractBase * aPtr; }; ... Concrete() : AnInterface(this) {} 

2 – créer une méthode abstraite dans l’interface et l’implémenter pour la renvoyer dans la classe concrète – ajoute au temps système indirection pour l’appel virtuel

 class AnInterface { virtual AbstractBase * getPtr() = 0; }; class Concrete : public AbstractBase, public AnInterface { AbstractBase * getPtr() { return this; } }; 

3 – dynamic_cast est encore pire

Existe-t-il un moyen plus efficace d’y parvenir?

IMO si le découplage entre la classe de base et l’interface est vraiment nécessaire, les solutions 1 et 2 ont des frais généraux tolérables, certainement rien qui puisse poser problème sur le matériel contemporain.

Mais puisque vous dites que l’interface est conçue pour fonctionner avec les fonctionnalités fournies dans la classe de base, le découplage n’est peut-être pas une bonne chose.

Je veux dire que si le problème concerne l’inheritance de plusieurs interfaces dont toutes héritent de la classe de base, ou le problème du “diamant redouté” avec l’inheritance, vous pouvez simplement utiliser l’inheritance virtuel .

Toutes vos préoccupations semblent être des micro-optimisations. En supposant que vous ne puissiez vraiment pas séparer votre interface de votre implémentation (dans ce cas, pourquoi utilisez-vous des interfaces en premier lieu?), Je voudrais simplement utiliser dynamic_cast et en dynamic_cast avec cela, même si c’est assez lourd. Si j’étais bloqué sur une plate-forme où RTTI n’est pas une option, j’utiliserais l’option 2.

Votre conception a des défauts.

Vous devriez envisager d’utiliser CRTP à partir de l’aspect Mixin , ce qui vous évite de conserver un pointeur supplémentaire sur le béton dérivé.

 template class AnInterface { public: AnInterface() { Derived* derived = static_cast(this); AbstractBase* abstractBase = static_cast(derived); } // have AbstractBase * here ~virtual AnInterface() {...} // and here }; class Concrete : public virtual AbstractBase , public AnInterface { AbstractBase * getPtr() { return this; } };