2010-05-08 28 views
6

El escenario que genera esto es bastante complejo así que voy a retirar de él unas pocas piezas y dar una representación exacta de las clases involucradas.C++ herencia múltiple Pregunta

/* This is inherited using SI by many classes, as normal */ 
class IBase 
{ 
virtual string toString()=0; 
}; 

/* Base2 can't inherit IBase due to other methods on IBase which aren't appropriate */ 
class Base2 
{ 
string toString() 
{ 
    ... 
} 
}; 

/* a special class, is this valid? */ 
class Class1 : public IBase, public Base2 
{ 
}; 

¿Es esto válido? ¿Habrá conflictos en el toString? ¿O puede Class1 usar Base2 :: toString para satisfacer IBase? Como digo, hay muchas otras cosas que no se muestran, por lo que las sugerencias para cambios de diseño importantes en este ejemplo probablemente no sean tan útiles ... aunque cualquier sugerencia/consejo general es bienvenido.

Mi otro pensamiento fue algo como esto:

class Class1 : public IBase, public Base2 
{ 
virtual string toString() 
{ 
    return Base2::toString(); 
} 
}; 

Esto construye y enlaces, pero no tengo idea de si se ha ocultado errores.

Respuesta

2

Puedes solucionar este problema utilizando "herencia virtual".

considerar la creación de una clase base común que solamente define un método virtual pura toString (o, en realidad, la versión virtual pura de cualquier método que tiene sentido tanto para IBase y Base2 tener), por ejemplo

class Stringable { 
    public: 
    virtual string toString() = 0; 
}; 

Entonces, tienen tanto IBase y Base2 heredan de esta clase Stringable:

class IBase : public Stringable 
{ 
}; 

class Base2 : public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Ahora bien, esto ya que todavía no funcionará porque Class1 se han heredado dos copias de la base Stringable clase, solo uno de los cuales tiene una implementación para toString en su jerarquía de herencia. Esto se conoce como "dreaded diamond". Sin embargo, si IBase y Base2 fueron a heredar prácticamente de Stringable, así:

class IBase : virtual public Stringable 
{ 
}; 

class Base2 : virtual public Stringable 
{ 
public: 
    virtual string toString() 
    { ... } 
}; 

Entonces este le dice al compilador que sólo debe haber una clase Stringable base común incluso si IBase y Base2 se heredaron por uno clase, que es exactamente lo que quiere, porque entonces el Base2::toString se usa para Class1.

Su segunda idea no tiene "errores ocultos", pero es algo de un dolor en el trasero para poner en práctica en repetidas ocasiones, como usted probablemente notará.

1

Esto debería funcionar bien.

Está sobrescribiendo correctamente la interfaz de IBase para proporcionar una definición de ToString() que se deshabilitará hasta Base2::ToString().

Tenga en cuenta que Base2 no declara toString() como virtual, por lo que Class1 no puede anular el comportamiento de Base2::ToString. Sin ambigüedad allí.

Y, además, este no es el clásico problema de diamantes en herencia múltiple resuelto por virtual inheritance porque no comparten una clase base.