2012-02-22 17 views
9

Estoy tratando de definir tipos de interfaz en C++ utilizando clases abstractas y ponerlas en práctica con clases concretas. El problema al que me estoy enfrentando es que no puedo heredar ni interconectar desde otra interfaz y heredar la implementación desde una clase concreta base.Implementación de interfaces en C++ con clases concretas heredadas

Mi objetivo es ser capaz de definir una jerarquía de interfaces que pueden heredar de interfaces base menos complejas. También quiero ser capaz de extender la implementación de interfaces heredando de clases concretas (como heredar de TObjectA en el ejemplo a continuación).

Esto es lo que tengo. El error que obtengo es "objeto de tipo de clase abstracta" TObjectB "no está permitido". Creo que sé por qué, que es porque no implementé MethodA() en TObjectB. Pero lo que realmente quiero es tener la implementación provista por una clase base (TObjectA) y aún tener jerarquías de interfaz (IInterfaceB hereda de IInterfaceA). Tampoco quiero repetir todos los métodos de interfaz heredados en mis clases de concreate derivadas. ¿Cómo puedo hacer esto?

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    IInterfaceB* b = new TObjectB(); // error: object of abstract class type "TObjectB" is not allowed 
    b->MethodB(); 
    delete b; 
} 
+2

Necesita clases base virtuales. P.ej. [mira aquí] (http://stackoverflow.com/questions/4605556/when-virtual-inheritance-is-a-good-design/4606206#4606206) –

Respuesta

11

En su jerarquía de clases, TObjectB tiene en realidad dos subobjetos clase IInterfaceA de base: una heredada a través IInterfaceB y una heredada a través TObjectA. El MethodA() de cada uno de ellos debe implementarse.

Necesitas heredar de las clases de interfaz utilizando pública virtuales herencia, lo que asegura que sólo hay un único subobjeto clase base de cada tipo de clase de interfaz:

class IInterfaceA 
{ 
public: 
    virtual void MethodA() = 0; 
}; 

class IInterfaceB : public virtual IInterfaceA 
{ 
public: 
    virtual void MethodB() = 0; 
}; 

class TObjectA : public virtual IInterfaceA 
{ 
public: 
    void MethodA() { cout << "Method A"; } 
}; 

class TObjectB : public TObjectA, public virtual IInterfaceB 
{ 
public: 
    void MethodB() { cout << "Method B"; } 
}; 

void TestInterfaces() 
{ 
    TObjectB b_object; 
    IInterfaceB& b = b_object; 
    b.MethodB(); 
} 

Sea o no este tipo de jerarquías de clases complejas son deseable es otro asunto en total.

+0

Cuando uso tu código recibo la siguiente advertencia "Advertencia:" TObjectB ': hereda' TObjectA :: TObjectA :: MethodA 'a través del dominio ". también cuando cambio la prueba a utilizar objetos montón asignado I obtiene un error de tiempo de ejecución afirmación y detiene la ejecución: TestInterfaces void() { IInterfaceB * b = new TObjectB(); b-> MethodB(); borrar b; } – sysrpl

+0

Sus clases de interfaz deben tener destructores virtuales si tiene la intención de eliminar objetos de forma polimórfica a través de ellos. En cuanto a la advertencia: evite las jerarquías de herencia complejas. –

1

Su problema es causado por la temida herencia de diamantes. Ha implementado TObjectA::IInterfaceA::MethodA pero no IInterfaceB::IInterfaceA::MethodA.

Mi recomendación sería hacer que IIterfaceA y IIterfaceB sean completamente independientes. Si eso no es posible, puedes ver la herencia virtual.

Cuestiones relacionadas