Scope eines "private Members"



  • So den Code in Form gebracht. Doch er kompiliert das schon.



  • Das geht schon immer so. Weil das Objekt im Parameter von CompareTo von der selben Klasse ist wie die Funktion die du gerade schreibst, wird davon ausgegangen, dass du die Interna kennst 🙂

    Die Semikola am Ende der Funktionsdefinitionen braucht es übrigens nicht.



  • martin_zi schrieb:

    Hat sich das mal geändert oder ging das schon immer so?

    Das ging schon immer so. Was zu beachten ist: private heißt, dass der Zugriff nur innerhalb der Klasse erlaubt ist. Es heißt nicht, dass der Zugriff nur innerhalb des jeweiligen Objektes erlaubt ist. Andersrum bedeutet das, dass Methoden von MyClass durchaus auch auf die privaten Member anderer Instanzen von MyClass zugreifen können.

    Mit dem Scope (Gültigkeitsbereich) haben Zugriffsspezifizierer übrigens nichts zu tun. Der Scope einer m_Member-Instanz reicht vom Beginn des Konstruktor-Rumpfes (genauer: ab der vorhergehenden Initialisierung der Membervariablen) bis zum Ende des Destruktor-Rumpfes. Und zwar egal ob grade eine Methode des Objektes aufgerufen wird oder ob es nur irgendwo in einem Container rumgammelt oder sonstwas 😉



  • Hi

    Ja danke für die Aufklährung :). Hba das wohl immer ein bisschen falsch gesehen. Das eröffnet mir ja ganz neue Möglichkeiten ;).

    Grüße
    Martin



  • Bei protected gibts eine Sonderregel, die Zugriff auf Basisklassenmember nur erlaubt, wenn es sich um das eigene Objekt handelt. Angesichts der Tatsache, dass protected alleine für Vererbung konzipiert ist, ist das auch vernünftig (auch wenn damit einige sinnvolle Fälle verhindert werden).



  • Nexus schrieb:

    (auch wenn damit einige sinnvolle Fälle verhindert werden).

    Das kann nichts sinnvolles verhindern - es wird evtl. nur etwas umständlicher:

    class base
    {
    protected:
      int foo();
      const float& bar() const;
    };
    
    class derived : public base
    {
    public:
      void wont_work(derived& other)
      {
        //int i1 = other.foo(); //NOPE
        //float f1 = other.bar(); //ERROR
      }
    
    //aber:
    private:
      int base_foo()
      {
        return foo();
      }
    
      float const& base_bar() const
      {
        return bar();
      }
    
    public:
      void will_work(derived& other)
      {
        int i2 = other.base_foo();
        float f2 = other.base_bar();
      }
    };
    

    Das einzige was man nicht hinkriegt, ist ein Zugriff auf die protected Member eines base, das kein derived ist - und das sollte man auch nicht weils eben nur für die eigenen Kinder eines base gedacht ist, nicht für Kinder eines fremden base 😉



  • pumuckl schrieb:

    Das kann nichts sinnvolles verhindern - es wird evtl. nur etwas umständlicher:

    Ja, Umwege findet man natürlich (fast) immer.

    Aber man verhindert damit eben dennoch etwas Sinnvolles – nämlich eine einfache, intuitive Implementierung ohne unnötige Indirektion.



  • hm. Ich seh grade, dass der alte GCC auf Codepad das schluckt:

    #include <iostream>
    
    class base
    {
      int i;
    protected:
      base() : i(0) {};
      int foo() {return ++i;}
      const float& bar() const 
      {
        static float f;
        f = 1.2*i;
        return f;
      }
    };
    
    class derived : public base
    {
    public:
      void wont_work(derived& other)
      {
        int i1 = other.foo(); //NOPE
        float f1 = other.bar(); //ERROR
        f1 += i1;
        std::cout << f1 << "\n";
      }
    };
    
    int main()
    {
      derived d1;
      derived d2;
    
      d2.wont_work(d1);
    }
    

    /edit: MSVC2010 nimmts auch und warnt nur vor der conversion double->float 😉



  • Klar fressen die das, weil es vollkommen OK ist.
    Wieso sollte man nicht über eine Derived-Referenz auf die protected Varialben von Base zugreifen dürfen?



  • Die protected -Regel gilt nur für Basisklassenmember. Sonst wäre protected ja stärker eingeschränkt als private .



  • So hatte ich den Kommentar von Nexus verstanden, dass da das protected nur aufs eigene Objekt anwendbar ist.

    Nexus schrieb:

    Bei protected gibts eine Sonderregel, die Zugriff auf Basisklassenmember nur erlaubt, wenn es sich um das eigene Objekt handelt. Angesichts der Tatsache, dass protected alleine für Vererbung konzipiert ist, ist das auch vernünftig (auch wenn damit einige sinnvolle Fälle verhindert werden).

    folgendes geht natürlich nicht - hätte ich auch nicht erwartet:

    class base
    {
      int i;
    protected:
      base() : i(0) {};
      int foo() {return ++i;}
    };
    
    class derived : public base
    {
    public:
      void wont_work(base& other)
      {
        int i1 = other.foo(); //In member function 'void derived::wont_work(base&)':
                              //error: 'int base::foo()' is protected
    
        std::cout << i1 << "\n";
      }
    };
    


  • pumuckl schrieb:

    So hatte ich den Kommentar von Nexus verstanden, dass da das protected nur aufs eigene Objekt anwendbar ist.

    Zuerst war es ungenau, daher der Edit. Danach hab ich extra "Basisklassenmember" geschrieben. 😉

    pumuckl schrieb:

    folgendes geht natürlich nicht - hätte ich auch nicht erwartet

    Du vielleicht nicht. Mich hat es am Anfang schon etwas überrascht, dass die klassen- und nicht objektbezogenen Zugriffsspezifizierer hier eine Ausnahme haben.


Anmelden zum Antworten