Wieso kann ich eine private Methode aufrufen?
-
Folgender Code:
class IParent { public: virtual void foo( ) = 0; }; class Root : private IParent { private: virtual void foo( ) override; }; class Test { public: Test( IParent& p ) : m_parent(p) { m_parent.foo(); // Wieso kann ich hier eine private Methode von Root aufrufen? } private: IParent& m_parent; }; //Ausgeführter Code: Root root; Test t( root );
Der obige Code funktioniert, aber ich verstehe nicht wieso.
- Root erbt private von IParent, wieso kann ich dann ein Test-Objekt erzeugen mit einem Root Objekt?
- Außerdem: Im Test Ctor rufe ich die Methode foo() des Interfaces IParent auf. Wie kann das gehen, wenn doch Root die Methode als private markiert hat?
-
Welchen Compiler verwendest du? Denn der gcc(C++14), s. Ideone-Code, liefert dafür eine Fehlermeldung:
error: ‘IParent’ is an inaccessible base of ‘Root’
(wegen der privaten Vererbung)
Wenn du aber dieses Interface
public
vererbst:class Root : public IParent
, dann kompiliert es auch beim gcc, denn über das InterfaceIParent
ist die Methode ja alspublic
deklariert - und nur dies ist für den Compiler wichtig.
Nur wenn du dann direkt z.B.root.foo();
aufrufen würdest (s. geänderter Ideone-Code), dann kommt die Fehlermeldungerror: ‘virtual void Root::foo()’ is private within this context root.foo();
-
@compyler sagte in Wieso kann ich eine private Methode aufrufen?:
Root erbt private von IParent, wieso kann ich dann ein Test-Objekt erzeugen mit einem Root Objekt?
Ich bezweifle, dass dein Compiler das tatsächlich so erlaubt.
-
- Kannst du garantiert nicht. Kann es sein, dass dein echter Code dort
public
anstattprivate
-Vererbung hat? Falls ja:public
-Vererbung bedeutet eine "ist ein"-Beziehung, das heißt, einclass Root: public IParent
wäre gleichbedeutend mit "Root ist ein IParent". Und in dem Fall wäre klar, dass ein Root eine gültige angabe ist, dort wo ein IParent erwartet wird (Es wäre aber schlechtes Design, weil dies in diesem Fall LSP verletzen würde). So wie du es hast, mitprivate
, gilt aber nicht, das Root ein IParent wäre und der Compiler muss dir hier eine Fehlermeldung werfen. Meiner tut es jedenfalls. m_parent
ist doch vom TypIParent&
.IParent
hat eine public Methodefoo
. Warum bist du verwundert, dass du die aufrufen darfst? Der Compiler kann ja schließlich nicht wissen, dass du dort zur Laufzeit auf ein Root-Objekt verweist. Die public/private-Geschichten sind Compilezeithilfen, die dir helfen, besseren Code zu schreiben. Es geht nicht um ein Zugriffberechtigungssystem!
- Kannst du garantiert nicht. Kann es sein, dass dein echter Code dort
-
@th69
Also mein echter Code hat folgende Struktur:
void Root::method() {
new Test( *this ) ); // Das hier baut
}Aber das finde ich bereits seltsam dass das geht. Test will ja ein IParent und Root erbt von IParent PRIVATE. Sollte das nicht einen Compile-Fehler geben?
-
Ja, sollte es. Also nocheinmal: welchen Compiler verwendest du?
-
Bitte compilierbares Minimalbeispiel! Deine Frage ist schließlich, wieso ein gewisser Code compiliert, aber dein bisher gezeigter Code ist weder identisch zu dem Code, zu dem du diese Frage hast, noch compiliert er.
-
This post is deleted!
-
Benutzt du einen Borland-C++ Compiler? Dem würde ich so etwas zutrauen.