2017-12-05 3 views
3

Angenommen, es gibt zwei unveränderliche Klassen aus einer Bibliothek, A und B, bezogen wie hier:Wie erbt man privat vom Derivat einer Basisklasse, implementiert aber die öffentliche Schnittstelle der Basisklasse?

class A 
{ 
public: 
    virtual void doCustomThings() = 0; 
    virtual void doOtherThings() = 0; 
    void doSomething(); 
private: 
    SomeType1 someData; 
}; 

class B : public A 
{ 
public: 
    void doCustomThings() override; 
    void doOtherThings() override; 
    void someUsefulUtility(); 
private: 
    SomeType2 otherData; 
}; 

Ich versuche, die Schnittstelle von A in Bezug auf die einig in B zur Verfügung zu implementieren, so dass ich tun:

class C : public B 
{ 
public: 
    void doCustomThings() override; // uses B::someUsefulUtility() 
    // leave B::doOtherThings() not overridden 
private: 
    SomeType3 myData; 
}; 

Aber ich beabsichtige nicht, C-B sein, dh ich will nicht Verweis auf C-0 implizit konvertierbar sein, obwohl es in A& umwandelbar sein sollte.

Das erste, was mir in den Sinn kommt, ist die virtuelle Vererbung, und dann erben public A, private B. Aber die A und B Klassen in meinem Fall sind nicht editierbar, und für die virtuelle Vererbung, um hier zu arbeiten, muss ich class B erben als public virtual A.

Eine andere Idee ist, Zusammensetzung statt Vererbung in Betracht zu ziehen. Aber wenn ich von A ableite und B als ein privates Mitglied habe, werde ich nutzlos A::someData zweimal haben, was unelegant aussieht.

Gibt es einen guten Weg, so etwas wie class C : public A, private B, so dass es nur eine Basisklasse A geben würde, angesichts der oben genannten Einschränkungen?

+0

_But I C nicht die Absicht, B_ sein <- Haben Sie C wollen ein ... zu sein? – skypjack

+0

@skypjack Ja, ich möchte 'C' implementieren' A's virtuelle Methoden. – Ruslan

+0

Da B ein A ist, warum ist es wichtig, ob C zu B konvertiert? Es wird auch in A umwandelbar sein, da B ein A. – ttemple

Antwort

0

Ja, verwenden Sie private Vererbung und legte die gewünschten Mitglieder mit using frei.

class C : private B 
{ 
public: 
    using B::A;// to make it convertible to A 
    using B::doOtherThings; 

    void doCustomThings() override { 
     std::cout<<"C::doCustomThings()\n";  
    } 
private: 
    char myData; 
}; 

Working example.

+1

'C & amp;' ist dann nicht in "A & amp;" umwandelbar: z.B. 'A & ac=c;' hinzugefügt zu Ihrem Arbeitsbeispiel kompiliert nicht. – Ruslan

+0

@Ruslan Fixed, danke für das zeigen – amc176

0

Ja, nur Vererbung für A, Zusammensetzung zum B und delegieren an die B Element (nicht Basis)

class C : public A 
{ 
public: 
    void doOtherThings() override { myB.doOtherThings(); } 

    void doCustomThings() override { 
     std::cout<<"C::doCustomThings()\n";  
    } 
private: 
    B myB; 
    SomeType3 myData; 
}; 
+0

Wie löst dies das duplizierte 'A :: someData' Problem? – Ruslan

+0

Entweder Sie können es ignorieren oder ** das von Ihnen gewählte Schema ** kann sich nicht ** in allen Fällen korrekt verhalten – Caleth

Verwandte Themen