2

Dans ma conception de classe, je suis tombé sur le problème suivant:Classe de base abstraite casse-tête

class MyData 
{ 
    int foo; 
}; 

class AbstraktA 
{ 
public: 
    virtual void A() = 0; 
}; 

class AbstraktB : public AbstraktA 
{ 
public: 
    virtual void B() = 0; 
}; 

template<class T> 
class ImplA : public AbstraktA 
{ 
public: 
    void A(){ cout << "ImplA A()"; }  
}; 

class ImplB : public ImplA<MyData>, public AbstraktB 
{ 
public: 
    void B(){ cout << "ImplB B()"; } 
}; 

void TestAbstrakt() 
{ 
    AbstraktB *b = (AbstraktB *) new ImplB; 
    b->A(); 
    b->B(); 
}; 

Le problème avec le code ci-dessus est que le compilateur se plaindra AbstraktA :: A() n'est pas défini.

Interface A est partagée par plusieurs objets. Mais l'implémentation de A dépend de l'argument template. L'interface B est vue par le monde extérieur et doit être abstrakt.

La raison pour laquelle je voudrais ceci est que cela me permettra de définir l'objet C comme ceci: Définir C d'interface héritant de abstrakt A. Définir la mise en œuvre de C en utilisant un autre type de données pour le modèle A.

J'espère que je suis clair. Y a-t-il un moyen de le faire, ou dois-je repenser mon design?

+0

Je peux être stupide, mais pourquoi "abstrait" épelé "abstrakt". Est-ce intentionnel? –

+1

Hé, pas de raison du tout. Juste un résultat de ma langue maternelle :) –

+0

double possible de: http://stackoverflow.com/questions/254673/multiple-inheritance-from-two-derived-classes – Talvalin

Répondre

9

Vous avez deux chemins d'héritage de AbstracktA, vous mettre en œuvre AbstraktA :: A() que dans l'un d'eux, de sorte que le compilateur se plaint.

Vous souhaitez probablement hériter virtuellement de AbstraktA dans les deux cas, de sorte qu'il n'y ait qu'un seul objet de base AbstraktA (ajoutez virtual avant AbstraktA).

+0

Remerciez toi!! C'était tout. Qu'est-ce qu'une solution facile :) Je me souviens maintenant que j'ai lu sur l'héritage virtuel avant, mais parce que je n'ai jamais eu à l'utiliser en pratique, je l'ai complètement oublié. je craignais d'avoir à repenser ma conception parce que je ne pouvais pas trouver une solution de rechange qui permettrait de résoudre ce dans le bon sens. Merci encore. –

+0

Cela fonctionne, mais conduit à un avertissement du compilateur: "avertissement C4250: 'ImplB': 'inherits ImplA :: ImplA :: A' par la domination" Est-ce quelque chose à se préoccuper? – Talvalin

+0

@lalithv, c'est quelque chose à craindre si ce n'est pas ce que vous voulez. Dans ce cas, c'est ce que l'on veut. (Je pense que cet avertissement est dans la catégorie « pas très commun, a le plus faux positif que vrai, difficile d'éviter proprement en réorganisant le code dans le cas de faux positifs ») – AProgrammer

0

J'ai oublié d'ajouter aux destructeurs virtuels classes de base. Cela conduit à des erreurs d'exécution malloc je crois.

AbstraktB *b = new ImplB; 
b->A(); 
b->B(); 
delete b; 

En mode débogage, à l'instruction delete, GCC me donne: malloc: *** erreur pour 0x60e2c4 objet: pointeur étant libéré n'a pas été affecté

Je résolu ce problème en changeant les classes de base à :

class AbstraktA 
{ 
public: 
    virtual ~AbstraktA(){}; 
    virtual void A() = 0; 
}; 

class AbstraktB : virtual public AbstraktA 
{ 
public: 
    virtual ~AbstraktB(){}; 
    virtual void B() = 0; 
}; 
Questions connexes