Teilobjekt/Vererbung



  • Der Konstruktor X ( t1 p1,..., tn pn) : Y (q1,...,qm) {...}
    entspricht der Initialisierung eines Y-Teilobjektes als Teil
    eines X-Objektes.

    Ich verstehe das nicht.
    Als Beispiel wurden Klassen und Unterklassen genannt aber ich verstehe die Syntax im Allgemeinen nicht.

    Zum Beispiel:

    class SavingsAccount {
    int savingsInterest;
    Account a;
    public:
    SavingsAccount (euro
    b, string s, int r)
    : a (b,s)
    {savingsInterest =
    r;}
    }
    


  • mal einigermassen formatiert:

    class SavingsAccount
    { 
    	int savingsInterest; 
    	Account a; 
    public: 
    	SavingsAccount (euro b, string s, int r) 
    		: a (b,s) 
    	{
    		savingsInterest = r;
    	} 
    };
    

    hier wird erst der konstruktor von a aufgerufen (mit den argumenten b und s). danach wird der integralen variable savingsInterest r zugewiesen. könnte man ebenfalls in der initialisierungsliste machen (bzw. würde man auch richtigerweise):

    class SavingsAccount
    { 
    	int savingsInterest; 
    	Account a; 
    public: 
    	SavingsAccount (euro b, string s, int r) 
    		: a (b,s), savingsInterest(r)
    	{
    	} 
    };
    

    wichtig ist, dass du den unterschied zwischen konstruktoren und zuweisungen verstanden hast. in konstruktoren können u.u. dinge passieren, die du bei einer zuweisung nicht mehr nachholen kannst. diese :-notation unter dem konstruktor (initialisierungsliste) wird abgearbeitet, bevor der funktionsrumpf des konstruktors betreten wird.

    edit:
    bei vererbung ist es genau gleich, nur dass in der initialisierungsliste kein member-bezeichner drin steht (wie auch lol), sondern der basisklassentyp:

    struct Base
    {
    	Base(int)
    	{
    	}
    };
    struct Derived : Base
    {
    	Derived()
    		: Base(42)
    	{
    	}
    };
    

    edit 2: es fällt natürlich auf, dass für das im edit 1 genutzte beispiel gar keine andere möglichkeit besteht:

    struct Base
    {
    	Base(int)
    	{
    	}
    };
    struct Derived : Base
    {
    	Derived()
    		// Keine eigene Initialisierungsliste -> der Compiler nutzt die Standard-Konstruktoren der Basen und der Member
    		// "Base" bietet aber keinen Standard-Konstruktor -> Compilerfehler
    	{
    		Base(42); // Hier wird einfach eine temporäre Instanz konstruiert
    	}
    };
    


  • Danke für die Ausführliche Antwort.

    Habe noch ein paar Fragen:

    1)Warum kann ich savingInterest(r) in oben hinschreiben. Ist das eine Kurzform für savingInterest=r?

    2)In deinem neuen Beispiel verstehe ich die Syntax nicht.
    Was ist dieses Base(int)?
    Was ist ein Memberbezeichner?

    In deinem Beispiel ist Base die Basisklasse und Derived die Unterklasse.
    Dann wird der Konstruktor von Base aufgerufen und anschließend der Konstuktor Derived ausgeführt wobei, dabei "nichts" passiert.



  • Ravend schrieb:

    1)Warum kann ich savingInterest(r) in oben hinschreiben. Ist das eine Kurzform für savingInterest=r?

    Ja, das ist quasi der Copykonstruktor eines ints.

    2)In deinem neuen Beispiel verstehe ich die Syntax nicht.
    Was ist dieses Base(int)?
    Was ist ein Memberbezeichner?
    

    Das ist die Signatur eines Konstruktors von Base.
    Ein von asdflol erfundener Begriff (Nach Google-Suche: offenbar auch von der MSDN verwendet; lol). Das ist der Name eines Members.
    Zum Initialisieren eines Members in der Initialisierungsliste schreibst du:
    membername(argumente) wie in dem Beispiel savingInterest(r). Um eine Basisklasse zu initialisieren, kannst du das nicht schreiben, weil du die Klasse nicht als Member hast, deswegen schreibst du da klassename(argumente), im Beispiel Base(42).



  • Ravend schrieb:

    1)Warum kann ich savingInterest(r) in oben hinschreiben. Ist das eine Kurzform für savingInterest=r?

    weil konstruktoren in der initialisierungsliste aufgerufen werden können. nein:

    int a; // Deklaration & Definition
    int b(3); // Deklaration & Definition & Konstruktoraufruf (bzw. initialisierung)
    int c = 3; // Deklaration & Definition & Konstruktoraufruf (das ist bisschen verwirrend aber eigentlich auch eindeutig)
    a = 3; // Zuweisung
    

    wenn du savingInterest(r) hinschreibst, dann passiert das selbe wie mit b und mit c (ist das selbe). wenn du in der initialisierungsliste nichts hinschreibst wird der standard-konstruktor aufgerufen. die regeln bei eingebauten typen sind da ein wenig speziell. es ist das selbe wie a -> undefinierter wert. erst die zuweisung "savingInterest = r" definiert den wert. das selbe wie bei a also. du kannst dir also aussuchen ob du das ganze in zwei (unnötigen) schritten machen willst oder in einem.

    Ravend schrieb:

    Was ist dieses Base(int)?

    ein konstruktor der einen int akzeptiert. da ich den parameter nicht brauche hab ich den bezeichner der parameters weggelassen. wäre gleich wie:

    Base(int Value)
    {
    }
    

    Ravend schrieb:

    Was ist ein Memberbezeichner?

    ein bezeichner ist sowas wie ein name. ein member ist eine variable bzw. eine instanz innerhalb einer klasse. somit ist ein member-bezeichner der name einer variable innerhalb einer klasse.

    Ravend schrieb:

    In deinem Beispiel ist Base die Basisklasse und Derived die Unterklasse.
    Dann wird der Konstruktor von Base aufgerufen und anschließend der Konstuktor Derived ausgeführt wobei, dabei "nichts" passiert.

    so ist es. es soll nur demonstrieren wieso diese initialisierungslisten unerlässlich sind. weil du sonst keine möglichkeit hast das argument des konstruktor-parameters der basisklasse (und auch der member) anzugeben.


Anmelden zum Antworten