2012-01-06 12 views
7

Co mam zamiar zrobić, to rozwijać dwie różne klasy bazowe, które nie powinny być dziedziczone razem w jednej klasie pochodnej. Czy istnieje sposób, w jaki mogę to wymusić w czasie kompilacji?Czy można zapobiec dziedziczeniu wielu klas bazowych podczas kompilacji?

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? 

Jestem świadomy, że documentation jest to dobry pomysł, po prostu zastanawiasz się, jeśli jest to możliwe.

+2

Myślę, że posiadanie prywatnego konstruktora może załatwić sprawę. Ale spowoduje również wyłączenie przypadku "Derived2". – littleadv

+0

Czy to nie wystarczy napisać "Nie rób tego!" w dokumentacji? –

Odpowiedz

8

Tworzysz pewien rodzaj sprzężenia między Base1 i Base2, ponieważ nie mogą one pochodzić z obu.

Moglibyśmy obaj wywnioskować z Base0, w którym to przypadku, jeśli wywodzisz się z Base1 i Base2, otrzymasz diament wielokrotny dziedziczenia, więc dostaniesz błąd kompilatora zakładając, że nie używasz wirtualnego dziedziczenia i nie rozwiążesz duplikacji .

To może rozwiązać twój problem, ale ja pytam, dlaczego próbujesz to zrobić.

(Klasa Base0 nie powinna być całkowicie pustą klasą, ponieważ musi istnieć coś niejednoznacznego, aby kompilator mógł złożyć skargę, i oczywiście można go rozwiązać, aby nie uniemożliwić czerpania z obu, tylko że wygeneruje wymagany "błąd" kompilatora, jeśli zrobisz to przez pomyłkę).

Przykładem może być:

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 dla "Pytam, dlaczego próbujesz to zrobić": każdy programista czujący potrzebę przejścia w dziedziczenie wielokrotne powinien znać konsekwencje – stijn

+1

proszę podać przykład jak można by pokazać błąd kompilatora ze wspólną bazą Base0 klasa? nie wydaje się oczywiste. to, że zarówno Base1, jak i Base2 dziedziczą z Base0, nie daje żadnych błędów. – codeling

+0

@nyalathotep To nie jest powód, aby losowo przysłać odpowiedź z pytania, które ma 2 lata, które użytkownik zaakceptował. Po prostu posiadanie pustego Base0 nie spowoduje problemu, musi tam być coś, co jest dziedziczone wielokrotnie, co powoduje konflikt. – CashCow

0

Interesującym problemem. Znalazłem rozwiązanie, które działa dla Microsoft (R) C/C++ Kompilator optymalizacyjny Wersja 18.00.31101 dla 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

Myślę, że użytkownik chciał błąd kompilacji nie aser wykonawczy. – CashCow

Powiązane problemy