2012-12-18 13 views
18

Könnten Sie bitte erklären, warum der folgende Code kompiliert und funktioniert (überprüft auf gcc-4.3.4). Ich dachte, selektive Vererbung kann den Zugang zu Mitgliedern/Methoden nicht schwächen oder sogar verstärken. Unterbindet es nicht die Kapselungsregeln?Selektive Vererbung C++

#include <iostream> 

class A { 
protected: 
    void foo() { std::cout << "foo" << std::endl; } 
}; 

class B : private A { 
public: 
    using A::foo; //foo() becomes public?! 
}; 

int main() { 
    B b; 
    b.foo(); 
    return 0; 
} 
+0

+1 für mich etwas beizubringen. –

+1

Sie tun dies, wenn Sie privat von Standardcontainern erben. Grundsätzlich verbieten Sie das Upcasting (das bedeutet, dass Sie keinen virtuellen Destruktor benötigen), aber Sie lassen einige Operationen zu, die mühsam neu implementiert werden könnten. –

Antwort

12

Aus der Sicht der Sprache ist nichts falsch daran (ob gutes Design eine andere Sache ist).

Jede Klasse kann sich entscheiden, einem breiteren Publikum Dinge zugänglich zu machen, auf die sie Zugriff hat.

Grundsätzlich Ihr Beispiel ist nicht anders zu:

class B : private A { 
public: 
    void bar() { foo(); } 
}; 

außer dass hier foo() durch einen Bevollmächtigten ausgesetzt ist.

Was Sie nicht tun können, ist das Gegenteil: Eine öffentlich abgeleitete Klasse kann den Zugriff auf Dinge, die über die Basisklasse zugänglich sind, nicht einschränken.

+1

Sicher kannst du; in 'Struktur A {int i; }; Struktur B: A {privat: mit A :: i; }; 'der Name' B :: i' Aliase und Schatten 'A :: i' mit privatem Zugriff. Das hält Sie natürlich nicht davon ab, 'b.A :: i' zu schreiben, was Sie vielleicht meinten. – ecatmur

+1

@ecatmur: 'B' kann Dinge verschleiern, aber es kann den Zugriff nicht einschränken. Ich kann immer den Bezug auf 'A &' verbessern und 'A's API verwenden:' A & a = b; a.i = 42; ' – NPE

+0

@ecatmur: Meine Wahl des Wortes * hide * war etwas unglücklich. Ich habe die Formulierung verbessert. – NPE