Frage zu protected



  • Wieso ist das hier nicht erlaubt?

    class A{
    protected:
      int a;
    };
    class B:public A{
    public:
      void foo(const A&b)
      {
        a=b.a;
      }
    };
    

    Ich weis, dass ich B friend von A machen muss aber wieso? Irgendwie ergibt diese Regel für mich keinen Sinn. Könnt jemeand mir das bitte erklären?



  • Hi,

    es ist ganz einfach, wenn du A übergibst, dann hat dieses Teil vorläufig nichts mit B zu tun, d.h. dass die abgeleitete Klasse zwar auf die protected-Elemente aus der Basisklasse zugreifen kann, die in der Instanz selber sind, aber nicht auf Elemente einer übergebenenen Klasse.
    friend ist meist minder schön, besser wäre es, eine kleine get-Methode zu schreiben:

    class A
    {
    ...
    inline int getA() const {return a;}
    ...
    };
    class B : public A
    {
    public:
    inline void foo(const A&b)
    {
    a = b.getA();
    }
    };
    

    MfG Eisflamme



  • Hi,
    Membervariablen sollten erstens einmal grundsätzlich nicht public oder protected sein.
    Zweitens, falls das, was du willst, erlaubt wäre, dann stell dir eine andere Klasse vor, die von der Basisklasse abgeleitet wird. Wenn du jetzt eine Instanz dieser Klasse als Argument an B::foo übergibst hättest du Zugriff auf protected und private Member von unverwandten anderen Klassen.
    Das könnte dann ziemlich verwirrend werden und private und protected könnten immer durch einfaches Hinzufügen einer neuen Klasse umgangen werden.
    Mögliche Lösungen:
    dynamic_cast nach B (Achtung: virtueller Destruktor)

    void B::foo (A* base) {
      if (B *b = dynamic_cast<B*>(base)) { 
         b->x = 42; 
      }
    }//Siehe auch Standard 11.5
    

    Oder deine Basisklasse stellt Funktionen zum modifizieren bereit.

    class A {
    protected:
       void do_sth_interesting (A *a) {
         a->x = 42;
       }
    
    private:
       int x;
    };
    
    class B : public A {
    public:
       void foo (A *a) {
         do_sth_interesting (a);
       }
    };
    


  • In meinem Beispiel sie A und B Wrapperklassen um C Funktionen. Die C Funktionen machen keinen Unterschied zwischen A und B, es sind immer die gleichen Funktionen. Nun kann man aber sehr stark optimiren wenn man weiß, dass ein Object read-only ist, deshalb A.

    Nun ist read-only aber nicht immer was man will und deshalb leite ich B davon ab und füge noch Veränderungsfunktionen hinzu.

    So nun hab ich eine Funktion von B die ein A als Argument nimmt. Die C Funktion fordert die Handles von Beiden, und hier macht es bum.

    Ich weis, dass A wie eine const B klingt allerdings sind die Klassen bereits im Konstruktor verschieden und soweit ich weis gibt es ja kein const Konstruktor.

    Was glaubt ihr wäre die beste Lösung?



  • Das funktioniert doch sowieso nicht. Wenn du in C ein A und ein B übernimmst und B ist von A abgeleitet, kannst du statt dem A dann auch ein B übergeben und der Compiler wird sich nicht beschweren.
    Ich finde es sowieso schlechten Stil, die Klasse abzuleiten um eine veränderliche Variante anzubieten. Entweder es macht für deine Klasse Sinn, mutable zu sein, oder nicht.
    Man sollte IMHO sowieso immer nochmal 2mal darüber nachdenken, ob man von konkreten Klassen erbt, ich persönlich brauche das sehr selten. Meistens habe ich eine Hierarchie, bei der nur die untersten Klassen konkret sind.

    Und wofür du einen "const Konstruktor" brauchst, habe ich beim besten Willen nicht verstanden.

    Nun kann man aber sehr stark optimiren wenn man weiß, dass ein Object read-only ist, deshalb A.

    Inwiefern? Klar können immutable Klassen schneller sein bei bestimmten Operationen, aber das musst du jetzt schon genauer ausführen.
    Jetzt mach erstmal ein gutes Programmdesign und optimieren kann man nachträglich immer noch.


Anmelden zum Antworten