2012-04-24 17 views
10

acabo trató esta pieza de código:La herencia múltiple: 2Classes1Method

struct FaceOfPast 
{ 
    virtual void Smile() = 0; 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() = 0; 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

...

void main() 
{ 
    Janus* j = new Janus(); 
    FaceOfFuture* future = j; 
    FaceOfPast* past = j; 

    future->Smile(); 
    past->Smile(); 

    delete j; 
} 

Funciona como destinados salidas (dos caras sonrientes), pero no lo hacen Creo que incluso debería compilar, la redeclaración de Smile() en Janus es ambigua.

¿Cómo (y por qué) funciona?

Respuesta

7

No hay ambigüedad porque se llama a Smile() de punteros a FaceOfFuture y FaceOfPast que solo declaran un método Smile().

Debido a llamar al método en un puntero de clase base no puede dar lugar a una ambigüedad, vamos a tratar las situaciones en las que se llama al método directamente en el puntero clase hija:

Janus* j = new Janus(); 
j->Smile(); 

La clase derivada, además de anular, también oculta la declaración de las clases base de Smile(). Usted tendría una ambigüedad sólo si usted no estaría reemplazando el método en su clase derivada:

Los siguientes compilaciones:

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 
int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

Aunque se llama Smile en un Janus, las declaraciones de clase base están ocultos .

La siguiente no:

struct FaceOfPast 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct FaceOfFuture 
{ 
    virtual void Smile() {printf(":) ");} 
}; 

struct Janus : public FaceOfPast, public FaceOfFuture 
{ 
}; 

int main() 
{ 
    Janus* j = new Janus(); 
    j->Smile(); 
} 

Debido a la ambigüedad.

+2

La pregunta no parece ser sobre la parte llamante, sino la parte redefinitiva: ¿por qué puedes redefinir 2 métodos virtuales con el mismo nombre de 2 clases diferentes escribiendo solo un método? – alexisdm

0
Janus* j = new Janus(); 
FaceOfFuture* future = j; 
FaceOfPast* past = j; 

Esta sección del código arroja una clase base. Por eso, cuando hace lo siguiente

future->Smile(); 
past->Smile(); 

Esto es real un puntero a una FaceofPast y FaceOfFuture.

1

Según la ++ estándar C (10.3.2):

Si un vf función miembro virtual se declara en una clase Base y en una clase Derivado, derivada directa o indirectamente de Base , una función miembro vf con el mismo nombre, parameter-type-list, cv-qualification y ref-qualifier (o la ausencia de la misma) como Base :: vf se declara, entonces Derived :: vf [ ...] reemplaza Base :: vf.

No parece haber ningún tratamiento especial para la herencia múltiple, por lo que muy probablemente se aplica aquí también: void Janus::Smile() anulaciones de ambos métodos sin ninguna ambigüedad, sólo porque tiene exactamente el mismo nombre y la firma ya que tanto la clase base métodos.