2012-01-06 12 views
7

Lo que estoy buscando hacer es desarrollar dos clases base diferentes que no deberían heredarse juntas en la clase derivada. ¿Hay alguna forma de que pueda aplicar esto en tiempo de compilación?¿Es posible evitar la herencia múltiple de clases base específicas en tiempo de compilación?

class Base1 {}; 
class Base2 {}; 
class Derived1 : public Base1 {} // OK! 
class Derived2 : public Base2, public Other {} // OK! 
class Derived3 : public Base1, Base2 {} // Can I force the compiler to complain? 

Derived1 d1; // OK! 
Derived2 d2; // OK! 
Derived3 d3; // Or can I force the compiler to complain here? 

Soy consciente de que documentation es una buena idea, preguntando si es posible.

+2

Creo que tener un constructor privado hará el truco. Pero también desactivará el caso 'Derived2'. – littleadv

+0

¿No es suficiente escribir "No hagas esto"? en la documentación? –

Respuesta

8

Está configurando algún tipo de acoplamiento entre Base1 y Base2 en el sentido de que no pueden derivarse ambos.

Puede hacer que ambos se derivan de Base0 en cuyo caso si deriva de Base1 y Base2 obtendría el diamante de herencia múltiple para que obtenga un error de compilador suponiendo que no usa herencia virtual y no resuelve la duplicación .

Eso podría resolver su problema, pero me pregunto por qué está tratando de hacer esto.

(Base0 no debería ser una clase totalmente vacía, ya que tiene que haber algo ambiguo que haga que el compilador se queje. Y, por supuesto, podrías resolverlo para que no te impida totalmente derivar de ambos, solo que generará el "error" del compilador requerido si lo hace por error).

Un ejemplo podría ser:

class Base0 
{ 
    protected: 
    virtual ~Base0(){}; 
    virtual void abstractMethod() const = 0; 
}; 

class Base1 : public Base0 
{ 
    protected: 
    virtual void abstractMethod() const; 

    // rest of Base1 
}; 

class Base2 : public Base0 
{ 
    protected: 
    virtual void abstractMethod() const; 

    // rest of Base1 
}; 

class Derived : public Base1, public Base2 
{ 
    // if I don't resolve abstractMethod it is ambiguous and the compiler will let me know 
}; 
+0

+1 por "Me pregunto por qué estás tratando de hacer esto": cualquier programador que sienta la necesidad de ir por herencia múltiple debe conocer las consecuencias – stijn

+1

por favor, ejemplifique cómo haría aparecer un error de compilación con una base Base0 común ¿clase? no parece obvio solo dejar que tanto Base1 como Base2 hereden de Base0 no está dando ningún error. – codeling

+0

@nyalathotep No es razón para rechazar una respuesta aleatoria de una pregunta que tiene 2 años de antigüedad que el usuario haya aceptado. Simplemente teniendo un Base0 vacío no habrá ningún problema, es necesario que exista algo heredado de forma múltiple que genere el conflicto. – CashCow

0

Un problema interesante. Encontré una solución que funciona para Microsoft (R) C/C++ Optimizing Compiler Versión 18.00.31101 para x64:

#include <iostream> 
#include <assert.h> 
using namespace std; 

class SuperBase { 
public: 
SuperBase():count(0) { 
    cout << "SuperBase constructor..." << endl; 
} 
~SuperBase() {} 
protected: 
int count; 
}; 
class Base1:virtual SuperBase 
{ 
public: 
Base1() 
{ 
    SuperBase::count++; 
    assert(SuperBase::count==1); 
    cout << "Base1 constructor..." << endl; 
} 

~Base1() 
{ 
    cout << "Base1 Destructor..." << endl; 
} 
}; 

class Base2:virtual SuperBase 
{ 
public: 
Base2() 
{ 
    SuperBase::count++; 
    assert(SuperBase::count==1); 
    cout << "Base2 constructor..." << endl; 
} 

~Base2() 
{ 
    cout << "Base2 Destructor..." << endl; 
} 
}; 

class Derived : public Base1, public Base2 
{ 
public: 
    Derived() 
    { 
    cout << "Derived constructor...." << endl; 
    } 
    ~Derived() 
    { 
    cout << "Derived Destructor..." << endl; 
    } 
}; 

class Derived1 : public Base1 
{ 
public: 
    Derived1() 
    { 
    cout << "Derived1 constructor...." << endl; 
    } 
    ~Derived1() 
    { 
    cout << "Derived1 Destructor..." << endl; 
    } 
}; 
class Derived2 : public Base2 
{ 
public: 
    Derived2() 
    { 
    cout << "Derived2 constructor...." << endl; 
    } 
    ~Derived2() 
    { 
    cout << "Derived2 Destructor..." << endl; 
    } 
}; 



int main() 
{ 
    cout << "Hello World" << endl; 
    Base1 b1; Base2 b2; 
    Derived1 d1; 
    Derived2 d2; 
    // Derived d; // - uncomment this line to get run-time error. 

    return 0; 
} 
+0

Creo que el usuario quería un error en tiempo de compilación, no una afirmación en tiempo de ejecución. – CashCow

Cuestiones relacionadas