Ce que je cherche à faire est de développer deux classes de base différentes qui ne doivent pas être héritées ensemble dans la classe dérivée. Y a-t-il un moyen de faire l'exécution de cela au moment de la compilation?
class Base1 {}; class Base2 {}; class Derived1 : public Base1 {} // OK! class Derived2 : public Base2, public Other {} // OK! class Derived3 : public Base1, Base2 {} // Can I force the compiler to complain? Derived1 d1; // OK! Derived2 d2; // OK! Derived3 d3; // Or can I force the compiler to complain here?
3 Réponses :
Vous mettez en place une sorte de couplage entre base1 et base2 en ce sens qu'ils ne peuvent pas être dérivés.
Vous pouvez les faire tirer de la base0 dans quel cas si vous découlez de base1 et de base2, vous obtiendrez le diamant multiple héritage afin que vous obteniez une erreur de compilateur en supposant que vous n'utilisez pas d'héritage virtuel et que vous ne résolvez pas la duplication. p>
qui pourrait résoudre votre problème, mais je me demande pourquoi vous essayez de le faire. p>
(base0 ne devrait pas être une classe totalement vide car il doit y avoir quelque chose qui doit y avoir quelque chose ambigu de faire compilateur à se plaindre. Et bien sûr, vous pourriez le résoudre afin que cela ne vous empêchent pas de dériver des deux, juste que cela générera «l'erreur» de compilateur requise si vous le faites par erreur). P>
Exemple peut être: p>
+1 pour "Je question pourquoi tu essaiez de le faire": tout programmeur ressentant la nécessité de passer à la manière multiple d'héritage devrait connaître les conséquences
S'il vous plaît donner un exemple comment créer une erreur de compilateur apparaît avec une classe de base de base0 commune? ne semble pas évident. Il suffit de laisser la base1 et la base2 hériter de base0 ne donne aucune erreur.
@nyalathotep qui n'est pas une raison pour indiquer de manière aléatoire une réponse d'une question de 2 ans que l'utilisateur a accepté. Juste avoir une base vide0, il n'y aura pas de problème, il doit y avoir quelque chose qui est multiplié hérité qui provoque le conflit.
Une réponse acceptée ne signifie pas nécessairement que c'est correct. Et c'est une raison de savoir si la réponse indique quelque chose qui est clairement faux. Citant "Vous pouvez les faire tirer de la base0 dans quel cas si vous découlez de base1 et de base2, vous obtiendriez le diamant multiple de héritage afin d'obtenir une erreur de compilateur" - vous seriez pas B> Obtenir une erreur de compilateur Dans ce cas (et jamais fait, pas même il y a 2 ans). Clarifiez cela et je vais rétracter mon bowvote.
Une réponse étant acceptée pourrait signifier que l'utilisateur l'a essayé et cela a fonctionné pour eux. Ils ont probablement compris que ma réponse avait ses limites, et le but était d'empêcher une personne découlant de manière accidentelle et non à bloquer totalement les solutions de contournement.
Un problème intéressant. J'ai trouvé une solution qui fonctionne pour Microsoft (R) C / C ++ Optimizing Compiler version 18.00.31101 pour X64:
#include <iostream> #include <assert.h> using namespace std; class SuperBase { public: SuperBase():count(0) { cout << "SuperBase constructor..." << endl; } ~SuperBase() {} protected: int count; }; class Base1:virtual SuperBase { public: Base1() { SuperBase::count++; assert(SuperBase::count==1); cout << "Base1 constructor..." << endl; } ~Base1() { cout << "Base1 Destructor..." << endl; } }; class Base2:virtual SuperBase { public: Base2() { SuperBase::count++; assert(SuperBase::count==1); cout << "Base2 constructor..." << endl; } ~Base2() { cout << "Base2 Destructor..." << endl; } }; class Derived : public Base1, public Base2 { public: Derived() { cout << "Derived constructor...." << endl; } ~Derived() { cout << "Derived Destructor..." << endl; } }; class Derived1 : public Base1 { public: Derived1() { cout << "Derived1 constructor...." << endl; } ~Derived1() { cout << "Derived1 Destructor..." << endl; } }; class Derived2 : public Base2 { public: Derived2() { cout << "Derived2 constructor...." << endl; } ~Derived2() { cout << "Derived2 Destructor..." << endl; } }; int main() { cout << "Hello World" << endl; Base1 b1; Base2 b2; Derived1 d1; Derived2 d2; // Derived d; // - uncomment this line to get run-time error. return 0; }
Je pense que l'utilisateur voulait une erreur de compilation et non un runtime affirment.
Si vous utilisez maintenant une nouvelle variante de C ++ (pas sûr de ce dont vous avez besoin pour STD :: is_base_of), cela pourrait vous aider:
J'ai confronté à un problème similaire, mais j'ai eu le luxe de construire toutes les instances possibles de Les classes dérivées possibles à travers une usine commune qui remettent des pointeurs à une autre classe de base de dérivée, que toutes les classes dérivées possibles partagent. p>
Donc, j'ai donc ce type de fonction d'usine modélisée sur le type dérivé réel. p> Ceci est facilité par le fait que toutes mes classes ont les mêmes arguments contenants, à savoir un type JSON, j'utilise la bibliothèque de N. Lohmann pour cela, mais il y en a d'autres. p> Ce n'est pas une méthode pour interdire strictement dériver jamais à la fois de base1 et de base2 n'importe où, mais peut-être interditer que dans cette fonction d'usine est suffisamment bonne pour la plupart des cas d'utilisation. P> P>
Je pense avoir qu'un constructeur privé fera le tour. Mais cela désactivera également le cas
dérivé2 code>.
N'est-il pas assez d'écrire "ne fais pas ça!" Dans la documentation?
Les développeurs ont lu la documentation?