Estoy teniendo un momento difícil con un temido problema de diamantes. Para un recordatorio, aquí es la jerarquía de clases clásica de este problema:Herencia virtual y temido diamante
B
/\
C1 C2
\/
D
Para solucionarlo, la solución estándar es hacer C1 y C2 utilizan la herencia virtual para heredar a partir de B.
Mi problema es que B y C1 son de un SDK que no puedo modificar. Ejemplo a continuación donde no puedo hacer SubClassB hereda virtualmente desde Base. Clases: PureVirtualBase, Base y SubClassB son del SDK que uso. No puedo modificarlos. SubClassA y Leaf son mis clases personalizadas. Puedo cambiarlos
PureVirtualBase(SDK)
|
Base(SDK)
/ \
SubClassA SubClassB(SDK)
\ /
Leaf
En tal situación, donde SubClassB no se puede cambiar a utilizar la herencia virtual desde Base. ¿Cómo lo debe de manera que:
- Hoja ejemplo sólo contiene una Base
- Evitar la ambigüedad cuando se trata de funciones de acceso definido puro virtual en PureVirtualBase e implementado en Base
class PureVirtualBase
{
public:
PureVirtualBase()
{
cout<<"<<PureVirtualBase::PureVirtualBase" << endl;
cout<<">>PureVirtualBase::PureVirtualBase" << endl;
}
virtual int f_PureVirtualBase()=0;
};
class Base : public PureVirtualBase
{
public:
Base(std::string id) {
cout<<"<<Base::Base:"<<id << endl;
m_id=id;
cout<<">>Base::Base:"<<m_id << endl;
}
virtual int f_PureVirtualBase() {
cout<<"Base::f_PureVirtualBase" << endl;
return 1;
}
private:
std::string m_id;
};
class SubClassA: public virtual Base
{
public:
SubClassA(): Base("From SubClassA") {
cout<<"<<SubClassA::SubClassA" << endl;
cout<<">>SubClassA::SubClassA" << endl;
}
};
class SubClassB: public Base
{
public:
SubClassB():Base("From SubClassB") {
cout<<"<<SubClassB::SubClassB" << endl;
cout<<">>SubClassB::SubClassB" << endl;
}
};
class Leaf: public SubClassA, public SubClassB
{
public:
Leaf():SubClassA(), SubClassB(), Base("From Leaf") {
cout << "<<Leaf::Leaf" << endl;
cout << ">>Leaf::Leaf"<< endl;
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Leaf myleaf;
myleaf.f_PureVirtualBase();
return a.exec();
}
- Si comentar la llamada a f_PurevirtualBase compila pero tengo una advertencia que base virtual 'Base' inaccesible 'hoja' debido a la ambigüedad Si descomentar esta llamada: Me sale este error: solicitud de miembro de ' f_PureVirtualBase' es ambiguo
- Si preceden a este llamado por el nombre de la clase (myleaf.SubClassA :: f_PureVirtualBase() entonces funciona, pero algo es obviamente erróneo, ya que hay 2 Base contenida en la Hoja Objeto).
¿Alguna pista?
Más información para responder a los comentarios
Mi arquitectura objetivo es un poco más compleja que la muestra que he proporcionado en la pregunta original:
PureVirtualBase(SDK)
|
Base(SDK)
|
--SubClassA
--SubClassB(SDK)
--SubClassC(SDK)
--SubClassD(SDK)
LeafOne: hereda de SubClassA y SubClassB (SDK)
LeafTwo: hereda de SubClassA y SubClassC (SDK)
LeafThree: hereda de SubClassA y SubClassD (SDK)
SubClassA es mi propio código privado. Proporciona funciones personalizadas. Debería poder tratarse como una instancia Base por métodos SDK. No se creará una instancia de esta clase pero está aquí para poder manejar LeafOne, LeafTwo y LeafThree en la misma cuando se realiza algún tratamiento.
¿Qué tal una clase heredada y otra compuesta? – iammilind
Es algo que estoy considerando, pero la integración de una Leaf Class tal no sería tan elegante en nuestro SDK y muchos problemas diferentes deberán resolverse. Aún tienes razón, es una manera de resolver este problema, pero me gustaría encontrar una manera de hacerlo a través de la herencia para una integración más fácil con las características del SDK. – Marc
¿Por qué crees que 'SubClassA' necesita heredar de' Base' en absoluto? Dada la definición de 'SubClassB' es obvio que' Base' no está diseñado para ser una clase base virtual en una jerarquía que incluye 'SubClassB'. –