Assoziation mit Pointer oder Instanz?



  • Gibt es einen Grund warum die "has a" Relation in einer custom-class oft durch einen Pointer (built-in oder Smart ) repräsentiert wird?

    class Foo{
     public:
      Foo() = default;
     private:
      Model * model_
    };
    

    Wo wäre der Nachteil hier einfach nen Steck Objekt zu verwenden?

    Ok man müsste nen Default Ctor im Model haben, damit dieser bei Konstruktion einer Instanz von Foo verwendet werden kann, aber was ist der wahre Grund?


  • Mod

    Ich nehme von der Namensgebung her doch mal stark an, dass Model hier eine virtuelle Basisklasse sein dürfte.



  • hier tatsächlich ja, aber meine Frage bezieht sich auf situationen ohne dynamic binding



  • Es könnte zum Beispiel noch sein, dass das Objekt sehr groß ist und/oder selten benutzt wird und somit nur stören würde.

    Ich finde dein "Steck-Objekt" (dem ich jetzt frech einen Bindestrich spendiere) übrigens eine interessante Wortschöpfung, die ich bislang nicht kannte. Ein Objekt, das in ein anderes hineingesteckt wird!



  • wob schrieb:

    Es könnte zum Beispiel noch sein, dass das Objekt sehr groß ist und/oder selten benutzt wird und somit nur stören würde.

    Ein weiterer Grund, mit dem ich z.B. häufig zu tun habe, wäre, dass das eher Objekt sehr oft benutzt wird, und zwar ein und die selbe Instanz von mehreren Foo s.
    Vielleicht ist Foo ja ein Suppenteller in einem Gourmet-Restaurant: Etliche stehen auf den Tischen verteilt und jeder verwendet das selbe 3D-Modell 😉
    Auf den Pointer oder etwas vergleichbares kann man eigentlich nur verzichten, wenn man eine 1:1-Beziehung hat.



  • aber dann verbietet sich auch die verwendung eines unique_ptr.

    steck object ist witzig, war aber nen typo.

    Ok merke gerade, dass in nem Fall dass die Member Variable als Instanz verwendet wird, und diese Teil einer Vererbungshierarchie ist, Destruktoren virtual sind und demzufolge auch die anderen special member functions definiert werden müssen. Dieser Aufwand entfällt bei der Pointervariante.

    Was ist dabei dann die bessere Option beim Übergeben einer Pointervariable?

    std::unique_ptr<BaseModel> _specificModel;
    
    void
    Foo::setModel(std::unique_ptr<BaseModel> model)
    {
        _specificModel.reset(model.release());
    //oder 
      _specificModel.swap(model);
    }
    


  • Sewing schrieb:

    aber dann verbietet sich auch die verwendung eines unique_ptr.

    steck object ist witzig, war aber nen typo.

    Aber ein Typo wofür? Du meinst doch nicht etwa "Stack"? Dass das falsch wäre, wird doch offensichtlich, wenn du "new Foo" machst.

    Ok merke gerade, dass in nem Fall dass die Member Variable als Instanz verwendet wird

    ???

    Was ist dabei dann die bessere Option beim Übergeben einer Pointervariable?

    std::unique_ptr<BaseModel> _specificModel;
    
    void
    Foo::setModel(std::unique_ptr<BaseModel> model)
    {
        _specificModel.reset(model.release());
    //oder 
      _specificModel.swap(model);
    }
    

    Ich schlage einfach den operator= vor.

    _specificModel = std::move(model);
    

  • Mod

    Halten wir mal fest:
    Default ist immer, dass das Objekt ein normaler Member ist. Jede Abweichung davon muss begründet sein. Legitime Gründe (bitte ergänzen, falls ich was vergessen habe):
    * Es geht nicht anders, weil Polymorphie
    * Es geht nicht anders, weil spezielle Anforderungen an die Ownership (geteilte Ownership; unkopierbare Objekte)
    * Es geht nicht anders, weil spezielle Anforderungen an die Lebenszeit
    * Es ist technisch sinnvoll, wenn das Subobjekt sehr groß sein sollte (Da muss man aber dem Programmierer des Unterobjekts einen Vorwurf machen. Das ist eigentlich dessen Verantwortung, dass ein solches Objekt seine Daten in den Freispeicher legt)



  • Alles klar, danke und dein Polymorphie Punkt bezieht sich eben darauf, dass in dem fall ein virtual dtor dann die definition der anderen ctors und assigment operatoren notwendig machen würde ja?


Log in to reply