Konstruktor von Objektelementen



  • Dafür war ich zu langsam ^^



  • Mach dir nix draus, ich hab auch 10 Minuten rumgerätselt, ob das jetzt wirklich mit dem Elementinitiali... also mit der Initialisierungsliste (<- danke für den Begriff, auch wenn ich mir net sicher bin, ob der viel besser ist X'D) so funktioniert. 🙂

    MfG Eisflammä



  • ah, das ging flott... thx!
    gleich mal testen. hätt ich ja auch drauf kommen können, dachte das funktioniert nur um parameter an konstruktoren in der hierachie nach "oben" zu reichen.



  • Nein, das Funktioniert auch mit built-in-Typen (z.B. int):

    class foo {
      int bar;
      foo() : bar(0) {}
    };
    


  • ja. Eben darauf bin ich dann auch gekommen ^^ und dann dachte ich mir: Mensch, dann muss das da doch auch gehn. X'D



  • okay, das funktioniert im prinzip schonmal.. danke nochmal.
    ABER, was mach ich im folgenden fall:

    class A
    {
      A(int x){y=x};
      int y;
    };
    class B
    {
      B(z=3):a(z)
      A a;
      int z;
    };
    

    der konstruktor von a wird aufgerufen, bevor z feststeht! 😞



  • Du solltest den Parameter von B nicht auch unbedingt z nennen (mal abgesehen davon das er keinen Typ bekommen hat ;)) und dann kannst du es z.B. so machen:

    class A
    {
      A(int x) : y(x) {}
      int y;
    };
    class B
    {
      B(int wert=3) : z(wert), a(wert) {}
      A a;
      int z;
    };
    


  • sorry, hab mich vertan, meinte folgendes:

    class A
    {
      A(int x){y=x};
      int y;
    };
    class B
    {
      B();
      A a;
      int z;
    };
    B::B() : a(z)
    {
      z=3 // nur ein Bsp, daß hier etwas mit z passiert, DIESES z soll a initialisieren
    };
    


  • Dann machst du es so ähnlich:

    class A
    {
      A(int x){y=x};
      int y;
    };
    
    class B
    {
      int z;
      A a;
      B();
    };
    
    B::B() : z(3), a(z)
    {
    }
    

    Zu beachten ist allerdings noch etwas bei dem Konstruktor:
    Damit z vor a initialisiert wird, muss z vor a deklariert sein in der Klasse. Die Reihenfolge in der Initialisierungsliste spielt keine Rolle, sondern die Reihenfolge der Deklaration der Variablen.



  • glaub ich kanns selber beantworten:

    class A
    {
      A(int x){y=x};
      int y;
    };
    class B
    {
      B();
      int z;
      A a;
    };
    B::B() : z(3), a(z)
    {
    };
    

    oder?



  • hehe, zeitgleich! 🙂
    naja, jetzt wirds dann leider doch off topic (bzw falsches forum):
    das prob is, daß z bei mir nich so einfach festgelegt wird wie im beispiel.
    es ist ein HWND und dem geht das füllen einer WNDCLASSEX und der aufruf von CreateWindowEx(...) voraus.
    falls du da noch weiterhelfen kannst?!?!
    werd mal schauen, ob ich das irgendwie hinbekomme..



  • Fast! 😉 Siehe meine Anmerkung. 🙂



  • Vellas schrieb:

    Fast! 😉 Siehe meine Anmerkung. 🙂

    hab doch z vor a deklariert! 🙂



  • Ops übersehen, sry. 🙂
    Zu dem anderen kann ich so nix sagen, hast da sonst nochmal ein Minimalbeispiel, wie das HWND gefüllt werden muss bzw. welche Operationen stattfinden müssen bevor "InfoDlg(hWnd, IDD_INFO);" aufgerufen werden soll?
    Ansonsten musst du wohl doch den Umweg über die temporäre Variable gehen.



  • das hab ich ihn etwa vor:

    class A
    {
      A(int x){y=x};
      int y;
    };
    class B
    {
      B();
      int z;
      A a;
    };
    B::B() : a(z)   // funktioniert nicht wie gewollt, da z noch nicht definiert
    {
      m = f();      // hier wird ein struct mit werten gefüllt
      z = g(m);     // z wird mittels dieses structs bestimmt
    };
    

    sowas dürfte funktionieren:

    class A
    {
      A(int x){y=x};
      int y;
    };
    class C
    {
      int z;
      C()
      {
        m = f();      // hier wird ein struct mit werten gefüllt
        z = g(m);     // z wird mittels dieses structs bestimmt
      };
    };
    class B
    {
      B();
      C c;
      A a;
    };
    B::B() : c() a(c.z)
    { 
    };
    

    für m hab ich mir mal die deklaration gespart...
    im prinzip sollte es so irgendwie funktionieren, oder?
    schön is das aber auch nich richtig. is dann wieder eine unnötige klasse. 😞

    noch ne andere idee, wenn ich m global mache (wäre nicht ganz unsinnig):

    B::B() : a(g(m))
    {
    };
    

    naja, werd mal schauen, was ich so hinbekomme. rumwurschteln hat ja eh imme rden besten lerneffekt! 🙂
    jedenfalls nochmal vielen dank!



  • Hi,

    also bei der Windowsprogrammierung geht es ja eigentlich immer um irgendwelche HWND-Strukturen oder so und da konstruiert man ja nichts durch den ctor sondern setzt einfach alle Werte.
    Na ja, davon abgesehen kannst du auch zur Laufzeit ein Objekt erstellen, wenn du mit Zeigern arbeitest.

    class Bla
    {
    Bla(int a, b) {}
    };
    
    class Blup
    {
    private:
    Bla* a;
    public:
    Blup(int c);
    ~Blup();
    };
    
    Blup::Blup(int c)
    {
    // mache irgendwas
    a = new Bla(x, y);
    }
    
    Blup::~Blup()
    {
    delete a;
    }
    

    Das macht man allgemein bei dynamisch bzw. zur Laufzeit erstellten Objekten so... Zu beachten ist dann aber, dass du zu einem new natürlich immer ein delete brauchst.
    Ob in deinem Fall Zeiger nötig sind, weiß ich aber gerade nicht zu beurteilen.

    MfG Eisflamme



  • Naja, entweder er benutzt Zeiger oder geht über eine temporäre Variable, wie er es zuvor gemacht hat. Da würde ich die Zeiger-Version noch bevorzugen.
    Oder aber er übergibt als Parameter einen entsprechenden Typ und initialisiert seine Variable damit:

    class foo {
      InfoDialog info;
    public:
      foo(InfoDialog infoDlg) : info(infoDlg) {}
    };
    
    int main() {
      // HWND irgendwo erstellen
      InfoDialog info(hwnd, IDD_INFO);
      foo(info);
    }
    

    Somit hätte er dann auch das Handle initialisiert, welches seine InfoStruktur benötigt.


  • Mod

    Mis2com schrieb:

    Hi,

    also bei der Windowsprogrammierung geht es ja eigentlich immer um irgendwelche HWND-Strukturen oder so und da konstruiert man ja nichts durch den ctor sondern setzt einfach alle Werte.
    Na ja, davon abgesehen kannst du auch zur Laufzeit ein Objekt erstellen, wenn du mit Zeigern arbeitest.

    class Bla
    {
    Bla(int a, b) {}
    };
    
    class Blup
    {
    private:
    Bla* a;
    public:
    Blup(int c);
    ~Blup();
    };
    
    Blup::Blup(int c)
    {
    // mache irgendwas
    a = new Bla(x, y);
    }
    
    Blup::~Blup()
    {
    delete a;
    }
    

    Das macht man allgemein bei dynamisch bzw. zur Laufzeit erstellten Objekten so... Zu beachten ist dann aber, dass du zu einem new natürlich immer ein delete brauchst.
    Ob in deinem Fall Zeiger nötig sind, weiß ich aber gerade nicht zu beurteilen.

    MfG Eisflamme

    dann nehmen wir aber am besten eine scoped_ptr, das hat nur vorteile:
    - scoped_ptr kann nicht kopiert werden, also kann der compiler auch für unsere klasse keinen copy-ctor und copy-zuweisungs op definieren. wenn wir diese wollen, müssten wir sie sowieso selbst definiern.
    - den destruktor brauchen wir nicht mehr
    - falls wir noch so ein member brauchen, ist das ganze gleich exceptionsicher, ohne etra noch try-catch kaskaden zu benötigen

    also:

    class Blup
    {
    private:
    boost::scoped_ptr<Bla> a;
    public:
    Blup(int c);
    };
    
    Blup::Blup(int c)
    : a() // ctor ist explicit
    {
    a.reset(new Bla(x,y));
    // mache irgendwas
    }
    

    für die eigentliche initialisierungsproblematik sei noch auf das hier http://www.boost.org/libs/utility/base_from_member.html verwiesen. das trifft das problem ja wohl exakt.


Anmelden zum Antworten