2010-11-26 5 views
11

J'ai une structure de classe beaucoup plus compliquée que celle-ci, mais en ramenant le problème à son essence, ceci décrit mon scénario: J'ai deux classes, A & B, qui implémentent des classes de base virtuelles pures qui partagent un ancêtre commun, puis une troisième classe C qui com-pose en principe un & B. Enfin, une classe de modèle qui remplit les méthodes communes dans la base virtuelle pure:Héritage ambigu des classes de base abstraites:

struct I { 
    virtual void r()=0; 
}; 

struct A : I {}; 
struct B : I {}; 

struct C : A, B { 
    void q(){ 
    r();    // the problem is here. 
    } 
}; 

struct D : C { 
    virtual void r(){ 
    } 
}; 

C* c = new D; 
c->q(); 

Mon problème est, je peux Ne voyez aucun moyen d'obtenir C :: q pour appeler r(). Comment puis-je appeler la méthode r() à partir de C afin que la méthode virtuelle correcte soit appelée? Désolé, j'aurais dû préciser que l'héritage virtuel ne peut pas être utilisé ici. J'ai trouvé deux solutions:

struct C : A, B { 
    virtual void r()=0; 
    ... 

OU

struct C : A, B { 
    using A::r; 
    ... 

Les deux semblent désambiguïser l'appel à r() suffisamment pour que tout résoudre.

+6

+1 pour prendre votre problème et le décomposer dans sa forme la plus simple. –

+0

Est-ce que r() ne sera pas ambigu en C sans héritage virtuel? – DumbCoder

+0

Voulez-vous dire la classe de base virtuelle ou simplement la classe de base abstraite?Parce que pour rendre 'I' une base virtuelle, vous avez besoin de' struct A: virtual I {}; 'et' struct B: virtual I {}; '. –

Répondre

4

méthode redéclarer r pure virtuel dans C:

struct C : A, B { 
    void q(){ 
    r();    // the problem is here. 
    } 

    virtual void r()=0; 
}; 
+1

Je ne sais pas pourquoi c'était la réponse acceptée. C'est un hack. La réponse correcte hérite pratiquement de I. – T33C

+0

Normalement je serais d'accord. Mais dans ma situation, je ne peux pas utiliser l'héritage virtuel. De toutes les solutions d'héritage non-virtuelles, c'est le plus élégant. –

2

Dites au compilateur quelle partie de la hiérarchie à suivre:

struct C : A, B { 
    void q(){ 
    A * p = this; 
    p->r();    // recent GCC compiles this 
    } 
}; 
3

Essayez l'héritage virtuel

struct A : virtual I {}; 
struct B : virtual I {}; 
2

Il est ambigu parce que le compilateur ne sait pas quel r() appeler, celui qui vient de A ou celui ing de B.

Le moyen facile est d'écrire:

static_cast<A*>(this)->r(); 

ou

static_cast<B*>(this)->r(); 

Mais je pense que rien de tout cela est la réponse que vous recherchez. Vous nettoyer la situation en héritant par virtual l'interface I:

struct A : virtual I {}; 
struct B : virtual I {}; 

Maintenant, vous pouvez appeler

void C::q() { r(); } 

que vous attendez. L'explication simple de ceci est que, en utilisant le virtuel, la classe C obtient seulement une "copie" de l'interface I, pas deux. Ceci désambiguise votre code.

+0

Vous ne devriez pas utiliser dynamic_cast plutôt que static_cast? Il y a des fonctions virtuelles impliquées. – DumbCoder

+0

Non, vous allez vers le haut de la hiérarchie, pas vers le bas. – Simone

-1

Vous n'avez pas surchargé r() dans les structures enfants, donc c'est encore virtuel pur. Je n'ai aucune implémentation.

+0

Non, ce n'est pas le problème. – Simone

Questions connexes