2010-11-26 13 views
11

Tengo una estructura de clase mucho más complicada que esta, pero reduciendo el problema a su esencia, esto describe mi escenario: Tengo dos clases, A & B, que implementan clases básicas virtuales puras que comparten un ancestro común, y luego una tercera clase C que com-postula una & B. por último, una clase de plantilla que llena en los métodos comunes en la base virtual pura:Herencia ambigua de clases base abstractas:

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(); 

Mi problema es, que pueda No veo ninguna forma de hacer que C :: q llame a r().

void C::q(){ 
    r(); // is ambiguous 
    A::r(); // is pure virtual 
    B::r(); // also is pure virtual 
    D::r(); // C doesn't know about D 
    ((D*)this)->r(); // is dubious and requires C to know about D. 
} 

¿Cómo puedo llamar al método r() desde C para que se llame al método virtual correcto?


Disculpa, debería haber aclarado que la herencia virtual no se puede utilizar aquí. He encontrado dos soluciones:

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

O

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

Ambos parecen eliminar la ambigüedad de la llamada a la r() lo suficiente para que todo se resuelve.

+6

+1 por tomar su problema y descomponerlo en su forma más simple. –

+0

¿No es r() va a ser ambiguo en C sin herencia virtual? – DumbCoder

+0

¿Quisiste decir clase base virtual o simplemente clase base abstracta?Porque para hacer que 'I' sea una base virtual necesita' struct A: virtual I {}; 'y' struct B: virtual I {}; '. –

Respuesta

4
método

redeclare r tan puro virtual en C:

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

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

No estoy seguro de por qué esta fue la respuesta aceptada. Es un truco. La respuesta correcta prácticamente hereda de I. – T33C

+0

Normalmente, estoy de acuerdo. Pero en mi situación no puedo usar herencia virtual. De todas las soluciones de herencia no virtuales, esta es la más elegante. –

2

Dile al compilador qué parte de la jerarquía a seguir:

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

Trate herencia virtual

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

Se es ambigua porque el compilador no sabe qué r() llamar, el que proviene de A o el que ing de B.

La manera más fácil es escribir:

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

o

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

pero creo que nada de esto es la respuesta que está buscando. A limpiar la situación heredando a través de la interfaz de E virtual:

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

Ahora, puede llamar

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

como era de esperar. La explicación simple de esto es que, al usar virtual, la clase C obtiene solo una "copia" de la interfaz I, no dos. Esto desambigua tu código.

+0

¿No debería estar utilizando dynamic_cast en lugar de static_cast? Hay funciones virtuales involucradas. – DumbCoder

+0

No, vas hacia arriba en la jerarquía, no hacia abajo. – Simone

-1

No ha sobrecargado r() en las estructuras secundarias, por lo que sigue siendo puramente virtual. es decir, no tienen implementación.

+0

No, ese no es el problema. – Simone

Cuestiones relacionadas