Klassenobjekte.



  • Also hallo miteinander. Ich verstehe nicht wie man Objekte als Element anderer Objekte erstellen kann.
    Also hier ist mein Kode um Konstruktoren zu verstehen:

    class A
    { 
    	public:
    		A() { cout << "A::Standardkonstruktor" << endl; }
    		~A() { cout << "A::Destruktor" << endl; }
    };
    
    class B : public A
    { 
    	public:
    		B(): A(){ cout << "B::Standardkonstruktor" << endl; }
    		~B() { cout << "B::Destruktor" << endl; }
    };
    class C
    { 
    	public:
    		C() { cout << "C::Standardkonstruktor" << endl; }
    		~C() { cout << "C::Destruktor" << endl; }
    };
    
    void main(void)
    { 
    	cout << endl;
    	cout << "Start main()" << endl;
    	//A a_obj; 
    	{B b_obj;}
    	//C c_obj; 
    	cout << "Ende main()" << endl;
    }
    

    Wie kann ich hier in die Klasse B ein normales Datenelement der Klasse C einfügen.Dieses Element soll das Schutzattribut private haben.
    Kann mir jemand da vielleicht weiterhelfen?



  • Zuerst: Der Destruktor von A muss virtual sein, da du eine Klasse von A ableitest. Ist er nicht virtual, kann das Objekt nicht korrekt abgebaut werden.

    #include <iostream>
    
    using namespace std;
    
    class C
    {
        public:
            C() { cout << "C::Standardkonstruktor" << endl; }
            ~C() { cout << "C::Destruktor" << endl; }
    };
    
    class A
    {
        public:
            A() { cout << "A::Standardkonstruktor" << endl; }
            virtual ~A() { cout << "A::Destruktor" << endl; }  //Wichtig!
    };
    
    class B : public A
    {
        public:
            B(): A(){ cout << "B::Standardkonstruktor" << endl; }
            ~B() { cout << "B::Destruktor" << endl; }
        private:
            C theC;  //privates Datenelement
    };
    
    int main(int argc, char **argv) {
        cout << endl;
        cout << "Start main()" << endl;
    
        A a_obj;
        {
          B b_obj;
        }
        C c_obj;
    
        cout << "Ende main()" << endl;
        return 0;
    }
    

    Außerdem sollte es int main heißen und main sollte bei Erfolg 0 zurückgeben.



  • GPC schrieb:

    Der Destruktor von A muss virtual sein, da du eine Klasse von A ableitest. Ist er nicht virtual, kann das Objekt nicht korrekt abgebaut werden

    ...wenn so ein Objekt über einen Zeiger auf A zerstört wird.

    Nicht grundsätzlich.



  • Klar, hatte ich vergessen, zu sagen.



  • Der Destruktor von A muß nicht virtual sein. Nur wenn ein B als A gelöscht wird, muß er virtual sein (alles klar?).

    Na dann besser ein Beispiel:

    A* a = new B();  // B ist von A abgeleitet
    delete a;        // Destruktor von A wird aufgerufen. Ist er nicht virtual
                     // wird der Destruktor nicht von B überschrieben und daher
                     // nicht aufgerufen.
    
    B* b = new B();
    delete b;        // Destruktor von B (und auch A) wird immer aufgerufen, da
                     // b den statischen Typ B hat.
    {
      B b;
    } // b hat statischen Typ B, daher wird der Destruktor immer aufgerufen
    

    Wenn ich die Objekte nicht dynamisch mit new erzeuge kann da gar nichts passieren.

    Tommi



  • Ich sollte nicht so lange erklären, sonst bin ich zu langsam mit der Antwort 😃



  • Start main()
    A::Standardkonstruktor
    C::Standardkonstruktor
    B::Standardkonstruktor
    B::Destruktor
    C::Destruktor
    A::Destruktor
    Ende main()
    Press any key to continue

    Das kommt als Ausgabe wenn man nur b_obj ausgibt. Warum wird hier der Konstruktor von C früher als der Konstruktor von B aufgerufen?



  • Also ich habe für das virtual so ein Beispiel gefunden:

    #include <iostream>
    using namespace std;
    
    class Base1 {
    public:
    ~Base1() { cout << "~Base1()\n"; }
    };
    
    class Derived1 : public Base1 {
    public:
    ~Derived1() { cout << "~Derived1()\n"; }
    };
    
    class Base2 {
    public:
    virtual ~Base2() { cout << "~Base2()\n"; }
    };
    
    class Derived2 : public Base2 {
    public:
    ~Derived2() { cout << "~Derived2()\n"; }
    };
    
    int main() {
    
    Base1* bp = new Derived1; // Upcast
    delete bp;
    
    Base2* b2p = new Derived2; // Upcast
    delete b2p;
    return 0;
    }
    

    Also wäre hier b2p richtig gelöscht aber bp wurde halt nicht alles löschen?
    Oder



  • Delikanli schrieb:

    Warum wird hier der Konstruktor von C früher als der Konstruktor von B aufgerufen?

    Weil Member vor dem Objekt selbst erzeugt werden.

    Delikanli schrieb:

    Also wäre hier b2p richtig gelöscht aber bp wurde halt nicht alles löschen?

    Richtig. Die Meldung "~Derived1()\n" dürfte nicht erscheinen.



  • Also d.h. dass die Klasse B sein Konstruktor zum schluss aufruft. Woher weisst der Compiler das? Egal auf jeden ist das so oder?

    Und noch was: Was ist ein statisches Element.



  • Und noch was: Was ist ein statisches Element.
    

    Ein statisches Element existiert nur einmal pro Klasse, ist also klassenspezifisch, und nicht wie normale Instanzvariablen der Klasse instanzspezifisch. D.h. alle Instanzen der Klasse teilen sich ein und dasselbe Element.



  • #include <iostream>
    using namespace std;
    
    class C
    { 
    	public:
    		C() { cout << "C::Standardkonstruktor" << endl; }
    		~C() { cout << "C::Destruktor" << endl; }
    };
    
    class A
    { 
    	public:
    		A() { cout << "A::Standardkonstruktor" << endl; }
    		~A() { cout << "A::Destruktor" << endl; }
    };
    
    class B : public A
    { 
    	public:
    		B(): A(){ cout << "B::Standardkonstruktor" << endl; }
    		~B() { cout << "B::Destruktor" << endl; }
    	private:
    	static C c_obj2;  //<<<<<================<<<<<============
    };
    
    void main(void)
    { 
    	cout << endl;
    	cout << "Start main()" << endl;
    	//A a_obj;
    	{B b_obj;}
    	//C c_obj; 
    	cout << "Ende main()" << endl;
    }
    

    <<<<========<<<<===== Also wenn ich C c_obj2; als statisches Element deklariere
    wird der Konstruktor von C nicht mehr aufgerufen. Warum?



  • Du hast c_obj2 gar nicht definiert. Würdest du darauf zugreifen, würde sich der Linker beschweren.

    In deinem Code fehlt

    C B::c_obj2;
    


  • Delikanli schrieb:

    <<<<========<<<<===== Also wenn ich C c_obj2; als statisches Element deklariere
    wird der Konstruktor von C nicht mehr aufgerufen. Warum?

    Das kommt daher weil du B::c_obj2 nur declariert aber nicht implementiert hast. Wenn du B::c_obj2 irgendwo verwenden würdest gäbe es einen Linker-Fehler.
    Richtig wäre

    C B::c_obj2;  // implementieren
    
    int main(void)
    {
        cout << endl;
        cout << "Start main()" << endl;
        //A a_obj;
        {B b_obj;}
        //C c_obj;
        cout << "Ende main()" << endl;
    }
    

    BTW: umbedingt lesen ( bald weigere ich mich solchen code auszuprobieren )
    http://www.research.att.com/~bs/bs_faq2.html#void-main

    EDIT: scheinbar schlafe ich noch



  • Aber auf der Seite 1 wurde es mir so gezeigt!?



  • Also ich muss C B::c_obj2; einfügen weil C c_obj2; ein statisches Element wurde oder wie sieht es jetzt aus. Ich bin ganz durcheinander jetzt und verstehe gar nichts mehr.



  • Delikanli schrieb:

    Also ich muss C B::c_obj2; einfügen weil C c_obj2; ein statisches Element wurde oder wie sieht es jetzt aus.

    So ist es. Wenn in einer Klassendeklaration ein statisches Element steht, ist das erst mal nur eine Deklaration. Das Element muss auch noch irgendwo definiert werden.



  • Delikanli schrieb:

    Aber auf der Seite 1 wurde es mir so gezeigt!?

    Wenn du damit das void main() meinst. Das zeigt dir hier keiner. 😉



  • Nein meine ich nicht. ich meine dass C c_obj2; ohne Definition!



  • Da wars nicht statisch.


Anmelden zum Antworten