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.

    1. Root erbt private von IParent, wieso kann ich dann ein Test-Objekt erzeugen mit einem Root Objekt?
    2. 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 publicvererbst: class Root : public IParent, dann kompiliert es auch beim gcc, denn über das Interface IParent ist die Methode ja als public 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 Fehlermeldung

    error: ‘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.


  • Mod

    1. Kannst du garantiert nicht. Kann es sein, dass dein echter Code dort public anstatt private-Vererbung hat? Falls ja: public-Vererbung bedeutet eine "ist ein"-Beziehung, das heißt, ein class 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, mit private, gilt aber nicht, das Root ein IParent wäre und der Compiler muss dir hier eine Fehlermeldung werfen. Meiner tut es jedenfalls.
    2. m_parent ist doch vom Typ IParent&. IParent hat eine public Methode foo. 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!


  • @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?


  • Mod

    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.

    Wie man Probleme nachstellbar und nachvollziehbar macht



  • Dieser Beitrag wurde gelöscht!


  • Benutzt du einen Borland-C++ Compiler? Dem würde ich so etwas zutrauen.


Anmelden zum Antworten