C ++ inheritance multiple virtuel pur?

J’ai besoin d’aide pour une implémentation utilisant plusieurs inheritances d’interfaces …

Il y a un code existant avec une interface qui a beaucoup de fonctions. Les instances sont créées à l’aide d’une fabrique.

class IBig { // Lot of pure virtual functions }; 

Et son implémentation:

 class CBig: public IBig { // Implementation } 

Je souhaite diviser l’interface en plusieurs interfaces plus petites, mais elle doit restr compatible avec le code existant pendant un certain temps.

Voici un exemple de ce que j’ai essayé de faire:

 class IBaseA { public: virtual void DoA() = 0; }; class IBaseB { public: virtual void DoB() = 0; }; // The same interface, now based on multiple smaller interfaces class IBig : public IBaseA, public IBaseB { }; class CBaseA: public IBaseA { public: virtual void DoA() { printf("DoA\n"); } }; class CBaseB: public IBaseB { public: virtual void DoB() { printf("DoB\n"); } }; // Inherit from base classes where the implementation is, and from IBig as // the instance of CBig is returned as IBig. class CBig: public CBaseA, public CBaseB, public IBig { }; 

Le problème ici est que la classe CBig ne peut pas être instanciée. Le compilateur dit que les fonctions DoA et DoB sont purement virtuelles, même si elles sont implémentées dans CBaseA et CBaseB. Que dois-je faire si je ne veux pas réimplémenter les fonctions, juste pour appeler la fonction de la classe de base?

NB: Je sais que le design est moche, mais ce n’est que temporaire jusqu’à ce que la grande interface puisse être remplacée, et …. je veux comprendre! 😉

Merci d’avance !

Ici, vous devez utiliser l’inheritance virtuel . Cette fonctionnalité garantit qu’il n’y a qu’une seule instance de votre classe de base virtuellement héritée lorsque vous instanciez une sous-classe. Pour votre exemple, cela ressemblerait à:

 #include  class IBaseA { public: virtual void DoA() = 0; }; class IBaseB { public: virtual void DoB() = 0; }; // The same interface, now based on multiple smaller interfaces class IBig : virtual public IBaseA, virtual public IBaseB // ^ ^ { }; class CBaseA: virtual public IBaseA // ^ { public: virtual void DoA() { printf("DoA\n"); } }; class CBaseB: virtual public IBaseB // ^ { public: virtual void DoB() { printf("DoB\n"); } }; // Inherit from base classes where the implementation is, and from IBig as // the instance of CBig is returned as IBig. class CBig: public CBaseA, public CBaseB, public IBig { }; int main() { CBig cb; } 

Les modifications ci-dessus garantissent qu’il n’y a pas de déclarations supplémentaires de DoA et de DoB créées lorsque vous IBaseA de IBaseA et IBaseB plusieurs resockets.

Ceci est connu comme le diamant mortel de la mort (ou simplement le problème du diamant). Cela se produit car CBig hérite de classes qui partagent des classes de base communes.

Vous pouvez soit appeler le bon DoA en le préfixant avec la classe à laquelle il appartient

 CBaseA::doA(); 

ou vous utilisez l’inheritance virtuel pour n’avoir qu’une seule instance d’IBaseA et IBaseB

 class CBaseA : public virtual IBaseA {}; class CBaseB : public virtual IBaseB {}; class IBig : public virtual IBaseA, public virtual IBaseB {}; 

etc…