Unterschiede Vererbung/Instanziierung von struct



  • Hallo,

    Frage:

    Was sind Unterschiede, Vor- Nachteile, ect. zwischen folgenden Implementierungen auch im Hinblick auf Vererbung:

    struct A
    {
     long lWert;
    }
    
    Class CA: private A
    

    und

    struct A
    {
     long lWert;
    }
    
    Class CA:
    {
    private:
    A m_strA;
    }
    

    Mir erscheint eine private Membervariable "sauberer".
    Meinungen dazu?



  • MFC-Coder schrieb:

    Mir erscheint eine private Membervariable "sauberer".
    Meinungen dazu?

    ja: rembrand?
    😕



  • Hallo,

    die Frage an sich ist nicht wirklich korrekt, weil beide Dinge eigentlich nichts miteinander zu tun haben. D.h. du nimmst entweder das eine wenn du das eine brauchst, oder du nimmst das andere wenn du das andere brauchst.

    - Private Vererbung bedeutet is implemented in terms of .
    - Eine private Membervariable stellt eine has-a Beziehung dar.

    Also nimmst du eine private Membervariable, wenn dein Datentyp ein Member is haben soll. Du nimmst private Vererbung, wenn du deinen Datentyp auf Basis von etwas aufbauen willst, z.b. noncopyable .



  • edit: Irgendwie verschrieben

    out schrieb:

    ...Also nimmst du eine private Membervariable, wenn dein Datentyp ein Member is haben soll...

    Also nimmst du eine private Membervariable, wenn dein Datentyp einen Member X haben soll.


  • Mod

    out schrieb:

    Du nimmst private Vererbung, wenn du deinen Datentyp auf Basis von etwas aufbauen willst, z.b. noncopyable .

    Zufällig etwas ungünstiges Beispiel, weil noncopyable als Member genausogut funktioniert. Hier steht bei der Vererbung eher der deklaratorische Wert im Vordergrund. Und noncopyable implementiert ja gerade nicht...



  • camper schrieb:

    bei der Vererbung eher der deklaratorische Wert im Vordergrund. Und noncopyable implementiert ja gerade nicht...

    Kannst du das genauer spezifizieren? Eventuell ein sinnvolles Beispiel machen?
    Ich wäre jetzt z.B. nicht auf die Idee gekommen, noncopyable via has-a zu realisieren, ich find es es gut wie boost es macht. 🙂



  • Ein Typ ist nicht kopierbar, wenn ein Member von ihm nicht kopierbar ist...



  • theta schrieb:

    Ein Typ ist nicht kopierbar, wenn ein Member von ihm nicht kopierbar ist...

    Ja, ich meinte was anderes. Ich fragte nach einem Beispiel, wo private Vererbung wirklich sinnvoll ist, und was camper mit "deklaratorische Wert im Vordergrund" genau meint. 🙂



  • camper schrieb:

    Zufällig etwas ungünstiges Beispiel, weil noncopyable als Member genausogut funktioniert. Hier steht bei der Vererbung eher der deklaratorische Wert im Vordergrund.

    Prinzipiell lässt sich jede private Vererbung über Member umsetzen, wenn der besagte Typ nicht virtuell ist, sogar ohne Zusatzklassen. Der Grund für private Vererbung kann Schreibaufwand sparen (bei boost::noncopyable do_not_copy_this_class; der Variablennamen), der deklaratorische Wert class X : boost::noncopyable lies: "class X is noncopyable") oder -- hier wohl der Hauptgrund -- EBO sein (wer würde boost::noncopyable ohne EBO verwenden?). Eine Alternative wäre ihn in std::tuple zu speichern, aber der Platz ist zu wenig prominent.

    Insofern finde ich boost::noncopyable das ein gutes Beispiel.



  • out schrieb:

    Ich fragte nach einem Beispiel, wo private Vererbung wirklich sinnvoll ist

    Stichwort "NVI".

    Private Vererbung ist dann notwendig, wenn in der Basisklasse das "Non Virtual Interface" angewendet wird:

    class Base
    {
      public:
        int Calculate()
          {
            if (DoCalculate())
              return 1;
    
            return 0;
          }
    
      private:
        virtual bool DoCalculate() = 0;
    };
    
    class Derived : private Base
    {
      virtual bool DoCalculate()
        {
          return true;
        }
    };
    


  • Bei NVI nimmt man public Vererbung.



  • Kellerautomat schrieb:

    Bei NVI nimmt man public Vererbung.

    Warum?



  • daddy_felix schrieb:

    Kellerautomat schrieb:

    Bei NVI nimmt man public Vererbung.

    Warum?

    Die Frage lässt sich auch in die Gegenrichtung stellen:
    Warum die öffentliche Schnittstelle der Basisklasse in diesem Fall nicht auch für die abgeleiteten Klassen anbieten? Warum sollte man in deinem Beispiel "Calculate" nicht direkt auf der abgeleiteten aufrufen können?

    Private Vererbung halte ich eher dann für sinnvoll wenn man ein funktionelle Vererbung haben, aber nicht nach außen die gleiche Schnittstelle anbieten will.



  • asc schrieb:

    Warum sollte man in deinem Beispiel "Calculate" nicht direkt auf der abgeleiteten aufrufen können?

    weil es sich um ein einfaches Beispiel zum NVI handelt, wo ich nicht mehr Gehirnschmalz als unbedingt nötig reinstecken wollte.

    "Calculate" darf nicht direkt aufgerufen werden, weil "Derived" erst einen Mutex setzen muss. Und bevor wieder gemeckert wird: Klar, könnte man den Mutex auch in Base setzen. Aber wenn Base zu einer externen Lib gehört, lässt sich das nicht ändern.

    oder

    Es ergibt keinen Sinn, "Calculate" von außen aufzurufen, weil Base als Timer implementiert ist, der periodisch prüft, ob die abgelaufene Zeit einen Schwellenwert überschreitet und wenn ja, die private Funktion aufruft.

    Klar könnte man das alles sicher auch anders modellieren. Aber nur, weil mir jetzt keine 100% überzeugenden Beispiele einfallen, muss das Konzept ja nicht prinzipiell schlecht sein. Oder gibt es gute Gründe, warum NVI immer public sein sollte?

    edit:

    asc schrieb:

    Private Vererbung halte ich eher dann für sinnvoll wenn man ein funktionelle Vererbung haben, aber nicht nach außen die gleiche Schnittstelle anbieten will.

    genau. Und ich will die Funktion von "Base" nuzten und intern "Calculate" aufrufen, ohne diese Schnittstelle nach außen anzubieten.


Anmelden zum Antworten