Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Reihenfolge bei der Objekterstellung

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 < [ 2 ]
000
12.08.2005, 13:01 Uhr
Reiko



Hi.

Ich hab hier die eine oder andere Frage zu den Aktionen, die bei einer Objekterstellung ablaufen. Dabei will ich möglichst <B>detailliert</B> in Erfahrung bringen, was im folgenden abläuft.

------------------------------------------------------------
class X
{
public: X(){printf("Standard-Konstruktor\n");
X(){printf("Copy-Konstruktor\n");

int a;
};

Ich definiere die beiden konstruktoren, welche ja automatisch vom Compiler erzeugt werden neu, damit ich ihre Aufrufe verfolgen kann.
------------------------------------------------------------
Der Code:

X alpha; // Zeile 1: Ausgabe: Standard-Konstruktor
X beta(); // Zeile 2: Ausgabe: (keine Ausgabe)
X zeta = X(); // Zeile 3: Ausgabe: Standard-Konstruktor,Copy-Konstruktor
------------------------------------------------------------

Alle Statements erzeugen ein Objekt bzw. bei allen 3en <B>sollte</B> ein Konstruktor aufgerufen werden (laut vorliegendem Buch - Borland C++ 3.1).
Das Problem ist für mich vor allem die unterschiedliche Syntax und deren Resultate; es sieht für mich so aus, als wenn jede dieser Zeilen unterschiedliche Aktion bei der Objekterstellung hervorruft.


Fragen zu Zeile 1:
------------------

Diese Syntax halte ich wegen der gemachten Ausgabe für die eigentliche Syntax bei der Objekterstellung, denn es wird, wie es sein sollte nur der Standard-Konstruktor aufgerufen - sehe ich das richtig?


Fragen zu Zeile 2:
------------------
Es erscheint keine Ausgabe, wieso? Wird etwa der vom Compiler voreingestellte Standard-Konstruktor X(); ausgeführt? Falls ja, wieso nicht mein überschriebener Standard-Konstruktor?

Kann es sein, dass hier ein temporäres unbenanntes Objekt erstellt wird, aus welchen Gründen auch immer?
=> laut Visual c++ 6.0 Handbuch dürfte hier kein temp. unbenanntes Objekt erstellt werden

=> Meine Vermutung bestätigt sich damit, dass ich keinen Zugriff auf die Attribute und Funktionen der Klasse habe mit einer Anweisung wie der folgenden: beta.a; oder beta.eineFunktion();
Bzw. kein Zugriff auf andere Funktionen und Attribute, die ich <B>hier</B> nicht in die Klasse mit aufgenommen habe.


Fragen zu Zeile 3:
------------------

Was hier passiert, ist mir ein Schleier, denn X zeta = X(); ruft zusätzlich noch den überschriebenen Copy-Konstruktor auf. Wieso?
(Im Buch steht nix darüber).

Deshalb will ich dieses Statement hier in die Reihenfolge einzelnen Schritte - so wie ich das sehe

1) X zeta // Objekterstellung + überschr. Standard-Konstruktor
2) X() // Erstellung eines temp + unbenannten Objekts ????
3) "=" // Copy-Konstruktor für zeta; kopiert wird der Inhalt des temp.
// Objekts

Seltsam ist Punkt 2) denn wenn ich X(); irgendwo im Code einfach so aufrufe, dann bekomme ich die Ausgabe: "Standard-Konstruktor"

Tatsächlich ist die Ausgabe der gesamten Zeile 3:
"Standard-Konstruktor"
"Copy-Konstruktor"

=> wenn in Punkt 2) also das passiert, was ich dort als Kommentar aufgeschrieben habe, dann müßte meiner Meinung nach die Ausgabe der Zeile 3 so aussehen:

"Standard-Konstruktor" // wegen X zeta
"Standard-Konstruktor" // wegen des anonymen + temp. Objekts
"Copy-Konstruktor" // wegen Kopie des Inhalts des anonymen + temp.
Objekts in das zeta-Objekt


Es ist ja so, dass bei einer Objekterstellung <B>immer</B> ein Konstruktor
aufgerufen wird; gilt auch der Umkehrschluß, dass bei jedem Konstruktoraufruf (z.B. X(); egal wo er erfolgt) auch ein Objekt erstellt wird?

Welche Rolle spielt der Zuweisungsoperator hier hat dieser bei Objekterstellungen eine andere Rolle als seine eigentliche (die elementweise Kopie)?


Fazit: Aufgrund der 3 unterschiedlichen Objekt-Erstellungs-Aufrufe (Zeile 1-3) kann man sich doch nie sicher sein, dass ein Objekt so initialisiert wird, wie es sein sollte bzw. die Litaratur stellt es so dar, als wenn alle 3 Aufrufe zum selben Ergebnis führen würden.
Wenn jemand noch ein gutes Buch kennt, dass ich mit den Interna von C++ beschäftigt, dann immer her damit ;-)

Dieser Post wurde am 12.08.2005 um 13:07 Uhr von Reiko editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
12.08.2005, 13:33 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von Reiko:
Hi.


C++:
class X
{
  public: X(){printf("Standard-Konstruktor\n");
          X(){printf("Copy-Konstruktor\n");

          int a;
};



Ich definiere die beiden konstruktoren, welche ja automatisch vom Compiler erzeugt werden neu, damit ich ihre Aufrufe verfolgen kann.
------------------------------------------------------------
Der Code:

X alpha; // Zeile 1: Ausgabe: Standard-Konstruktor
X beta(); // Zeile 2: Ausgabe: (keine Ausgabe)
X zeta = X(); // Zeile 3: Ausgabe: Standard-Konstruktor,Copy-Konstruktor
------------------------------------------------------------


Fragen zu Zeile 1:
------------------

Diese Syntax halte ich wegen der gemachten Ausgabe für die eigentliche Syntax bei der Objekterstellung, denn es wird, wie es sein sollte nur der Standard-Konstruktor aufgerufen - sehe ich das richtig?


Ja,

C++:
X alpha;


Ist die definition einer Variable namens alpha, die den Typen "X" hat. Wird die Variable erzeugt, wird der der Parameterliste entsprechende ctor aufgerufen. Der ctor ohne Paramete r ist eben der sog. Defaultconstructor.



Zitat:

Fragen zu Zeile 2:
------------------
Es erscheint keine Ausgabe, wieso? Wird etwa der vom Compiler voreingestellte Standard-Konstruktor X(); ausgeführt? Falls ja, wieso nicht mein überschriebener Standard-Konstruktor?



Nein. Es wird überhauopt kein ctor aufgerufen, weil die Zeile "X beta();" keine variabledefinition ist, sondern vom Kompiler als die Deklaration eine funktion namens "beta" angesehen wird, welche keine Parameter erwartet, aber ein X zurückgibt. Beliebter Anfängerfehler, aber auch beliebtes Beispiel für die kranke C++ Syntax.


Zitat:

Kann es sein, dass hier ein temporäres unbenanntes Objekt erstellt wird, aus welchen Gründen auch immer?
=> laut Visual c++ 6.0 Handbuch dürfte hier kein temp. unbenanntes Objekt erstellt werden

=> Meine Vermutung bestätigt sich damit, dass ich keinen Zugriff auf die Attribute und Funktionen der Klasse habe mit einer Anweisung wie der folgenden: beta.a; oder beta.eineFunktion();
Bzw. kein Zugriff auf andere Funktionen und Attribute, die ich <B>hier</B> nicht in die Klasse mit aufgenommen habe.



Sollte durch obigen Hinweis geklärt sein.


Zitat:

Fragen zu Zeile 3:
------------------

Was hier passiert, ist mir ein Schleier, denn X zeta = X(); ruft zusätzlich noch den überschriebenen Copy-Konstruktor auf. Wieso?
(Im Buch steht nix darüber).



Deshalb will ich dieses Statement hier in die Reihenfolge einzelnen Schritte - so wie ich das sehe

1) X zeta // Objekterstellung + überschr. Standard-Konstruktor
2) X() // Erstellung eines temp + unbenannten Objekts ????
3) "=" // Copy-Konstruktor für zeta; kopiert wird der Inhalt des temp.
// Objekts

Seltsam ist Punkt 2) denn wenn ich X(); irgendwo im Code einfach so aufrufe, dann bekomme ich die Ausgabe: "Standard-Konstruktor"

Tatsächlich ist die Ausgabe der gesamten Zeile 3:
"Standard-Konstruktor"
"Copy-Konstruktor"
[/quote]

Du kannst Diesen Ausdruck auch so schreiben:

C++:
X zeta(X())


Dh mit X() wird zunächst das temp. Objekt erzeugt (Standardctor). Und dann wird mit diesem temp. Objekt zeta über den copyctor erzeugt.
=> wenn in Punkt 2) also das passiert, was ich dort als Kommentar aufgeschrieben habe, dann müßte meiner Meinung nach die Ausgabe der Zeile 3 so aussehen:

Auch dies ist ein Beispiel für kranke C++ Syntax:
hier wird also X() richtigerweise als ctor aufruf interpretiert (ganz im gegensatz zum 2. Pubnkt oben) und gleichzeitig hat das "=" Zeichen eine andere bedeutung: Wird das "=" Zeichen bei der Variablendefinition verwendet, so wird der copyctor und nicht etwa der Zuweisungoperator aufgerufen. Dh bei folgender Klasse

C++:
class Y {
public:
     Y() { std::cout<<"dflt-ctor"<<std::endl; }
     Y(const Y&) { std::cout<<"copy-ctor"<<std::endl; }
     Y& operator = (const Y&) std::cout<<"zuweisung"<<std::endl; return *this; }
};


wird für

C++:
Y a;
Y b = a;


Ausgegeben:

Code:
dflt-ctor    (für a)
copy-ctor  (für b)


Dagegen bedeutet

C++:
Y a;
Y b;
b = a;



Code:
dflt-ctor    (für a)
dflt-ctor  (für b)
zuweisung (a nach b)


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
12.08.2005, 13:34 Uhr
Tommix



Hallo,
wie kommst Du nur auf den Trichter, daß der zweite CTor ein Copy-Konstruktor sei? Ein Copy-Konstruktor erzeugt ein neues Objekt unter zuhilfenahme eines bereits bestehenden. Dabei werden üblicherweise - aber nicht zwingend - die Member kopiert. Bezogen auf Dein Bsp. sähe das eher so aus:

C++:
#include <stdio.h>

class X
{
public:
    X(){printf("Standard-Konstruktor\n");}
    X(const X& x) : a(x.a) {printf("Copy-Konstruktor\n");}
        
    int a;
};


int main()
{
    X alpha; // Std-Ctor
    X beta(alpha);  // Copy-Ctor
    X zeta = alpha; // Copy-Ctor

    return 0;
}



Gruß, Tommix


Bearbeitung:

Wieso ist virtual mit seinem monumentalen Werk schneller als ich mit meinen paar Zeilen?


Dieser Post wurde am 12.08.2005 um 13:36 Uhr von Tommix editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
12.08.2005, 14:29 Uhr
Reiko



Moalz.

Danke Jungs, das ist ja geil! Soweit alles einleuchtend ... fast alles.


1) X beta();

Da hätt ich ja auch selbst draufkommen können - manchmal sieht man den Wald vor lauter Bäumen nicht mehr; wobei im buch echt steht, dass hier ein ctor aufgerufen wird !!!!!

an virtual:

Allerdings sagste ja selbst bei "X alpha;"
>Ist die definition einer Variable namens alpha, die den Typen "X" hat. Wird die Variable >erzeugt, wird der der Parameterliste entsprechende ctor aufgerufen. Der ctor ohne >Paramete r ist eben der sog. Defaultconstructor.

Ok, aber ich kann doch einen parameterlosen ctor auch mit leerer Klammer schreiben oder nicht ???
" X alpha(); "

vgl. X beta(); hier ist die "Parameter-LISTE" leer, aber immerhin hab ich hier eine angegeben, in der Hoffnung, dass es ein ctor-Aufruf ist => in diesem Fall wird der Ausdruck aber als Funktions-Deklaration ausgewertet, ok.


Also meintest du mit deiner Erklärung oben eher folgendes ?! Man muß beim parameterlosen ctor zwischen Syntax bei dessen Definition und Aufruf unterscheiden ?!

> ... Wird die Variable erzeugt, wird der der Parameterliste entsprechende ctor aufgerufen, >SOFERN ES SICH NICHT UM DEN PARAMETERLOSEN CTOR HANDELT; soll der parameterlose >ctor aufgerufen werden, dann läßt man die LEERE Parameterliste BEIM AUFRUF weg

>Der ctor ohne Parameter (besser: mit LEERER PARAMETERLISTE) ist eben der sog. >Defaultconstructor, ABER eben NUR BEI SEINER DEFINITION wird die Parameterliste >angegeben; bei Aufrufen wird sie weggelassen

Sorry für die Wühlerei in der Schei... aber ich mit ein "Definitions-Mensch" und muß alles zu 100% wissen.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
12.08.2005, 14:56 Uhr
virtual
Sexiest Bit alive
(Operator)


Also das ist bei C++ wirklich eine Krankheit:

C++:
X beta(); // Kein ctor aufruf
X beta;   // ctor aufruf


Diesen Umstand braucht man nicht zu verstehen, sondern muß ihn sich einfach merken.

Komm an dieser Stelle bloß nicht mit Logik! - Die gilt hier nämlich nicht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
12.08.2005, 16:34 Uhr
~Reiko
Gast


Hier bin ich nochmal kurz; hab hier noch was ...

2) X zeta(X())

Der Prototyp wäre also X(X& arg); der Copy-ctor, ok.

Eine Frage war noch unbeantwortet bzw. es ging aus deinen Ausführungen nicht hervor, ob jedem ctor-Aufruf die physikalische Objekt-Erstellung vorangeht bzw. ob jeder explizite ctor-Aufruf bedeutet, dass ein Objekt erzeugt wird?


C++:

int main(){
  X zeta(X())  // in diesem Fall wird doch der ein Objekt durch X() erzeugt, aber doch nur,  
                   //  weil es sich dabei um dem copy-ctor handelt <= verlangt Objekt-Referenz

  X();           // Wie siehts aber hier aus? Anonymes Objekt oder einfacher Konstruktor ohne
                  // Objekterzeugung?



Grund der Frage: Viele schreiben umkorrekterweise, dass ein Konstruktor ein Objekt erstellt, dabei wird das Objekt (Speicherplatzreservierung) ja vor dem ctor durchgeführt, sodass der ctor nur ein Initialisierer ist. Die andere Seite wäre, dass ein Konstruktoraufruf immer auch eine vorangehende Objekterstellung signalisiert.


Wie siets denn mit Konstruktorenverkettung in C++ aus, also der Aufruf 2er oder mehrer Konstruktoren derselben Klasse für ein einziges Objekt, wie man es aus Java kennt? Gibts das auch in C++?

Das wär dann auch wirklich alles ... zu diesem Thema ..... *fg*
Danke

Ciao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
12.08.2005, 17:11 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat von ~Reiko:


2) X zeta(X())

Der Prototyp wäre also X(X& arg); der Copy-ctor, ok.


Fast, der Prototyp sollte besser lauten

C++:
X(const X& arg);


const ist das Versprechen, daß arg im ctor nicht verändert wird. Das ist etwas anderes als final in Java: in Java bedeutet final ja erstmal nur, daß die Referenz des Objektes nicht geändert werden darf, das const geht einen Schritt weiter und drückt aus, daß der Inhalt des Objekts nicht verändert werden darf. Wenn Du nun

C++:
X(X& arg);


schreiben würdest, signalisierst Du damit dem Compiler, daß es möglich wäre, daß arg nach dem Aufruf des ctors einen anderen Inhalt haben könnte. Dies kann in bestimmten Situationen zu Problemen führen. Daher gewöhne dir frühzeitig an, bei Parametern, die nicht verändert werden, ein const davor zu setzen. Bei einem copy ctor ist dies im überwiegenden Teil der Fälle so.


Zitat:

Eine Frage war noch unbeantwortet bzw. es ging aus deinen Ausführungen nicht hervor, ob jedem ctor-Aufruf die physikalische Objekt-Erstellung vorangeht bzw. ob jeder explizite ctor-Aufruf bedeutet, dass ein Objekt erzeugt wird?

C++:

int main(){
  X zeta(X())  // in diesem Fall wird doch der ein Objekt durch X() erzeugt, aber doch nur,  
                   //  weil es sich dabei um dem copy-ctor handelt <= verlangt Objekt-Referenz

  X();           // Wie siehts aber hier aus? Anonymes Objekt oder einfacher Konstruktor ohne
                  // Objekterzeugung?



Grund der Frage: Viele schreiben umkorrekterweise, dass ein Konstruktor ein Objekt erstellt, dabei wird das Objekt (Speicherplatzreservierung) ja vor dem ctor durchgeführt, sodass der ctor nur ein Initialisierer ist. Die andere Seite wäre, dass ein Konstruktoraufruf immer auch eine vorangehende Objekterstellung signalisiert.


Du hast zwar recht, daß die Objekterstellung in zwei schritten Stattfindet, nämlich erst bereitstellung des Speichers und anschliessend die Initialisierung durch den ctor. Allerdings fallen diese Beiden dinge in der Regel zusammen. Es gibt zwar einige advanced features, wie man diese beiden Schritte trennen kann (Stichworte: "placement new" und "Allocatoren"), aber vereinfachend kann man sich vorstellen, daß beide Schritte zunächst untrennbar miteinander verbunden sind. Der Ausdruck "X();" erzeugt somit ein Objekt auf dem Stack und ruft den ctor auf. Da du keine Zuweisung an eine Variable machst bzw. dieses Objekt nicht direkt verwendest (wie in der Zeile darüber), ist das Objekt zwar da, aber nicht weiter referenzierbar.


Zitat:

Wie siets denn mit Konstruktorenverkettung in C++ aus, also der Aufruf 2er oder mehrer Konstruktoren derselben Klasse für ein einziges Objekt, wie man es aus Java kennt? Gibts das auch in C++?


Mir fällt der Fachbegriff nicht ein, aber ich glaube du meinst sowas:

Code:
public class JavaClass {
    public JavaClass(int x) {
       this(x, 0); // Meinst Du das?
    }
    public JavaClass(int x, int y) {
       ...
    }
}


Meinst du sowas? - Das geht nicht in C++. Man kann sich zwr behelfen mit

C++:
class CppClass {
public:

    CppClass(int x) {
       init(x);
    }
    CppClass(int x, int y) {
       init(x,y);
    }

    void init(int x, int y=0) {
    }
};


Aber das ist nur eine krücke, weil insbes. wenn man referenzen in C++ Klassen hat, geht dieser "Trick" nicht mehr: man muß nämlich Referenzen direkt über Initialisiererlisten im ctor initialisieren.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
14.08.2005, 01:39 Uhr
Reiko



Eine Frage noch mal zur Klasse oben.

Gegebenen Konstruktoren:

C++:
X(const X& arg);
X();
X(int a)




C++:
obj1;

X(obj1);  // Zeile 1
X(12);    // Zeile 2
X();       // Zeile 3



Zeile 1 + 2 führen zur Objekterstellung, Zeile 1 nicht. Wieso?
Danke
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
14.08.2005, 09:49 Uhr
FloSoft
Medialer Over-Flow
(Administrator)


du meinst Zeile 3 nicht, den Zeile 3 ist ein Funktionsaufruf. Das ist eben die stellenweise kranke C++-Syntax.
--
class God : public ChuckNorris { };
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
14.08.2005, 11:00 Uhr
~Reiko
Gast


Ja, ich meinte Zeile 1. Zeile 2 + 3 erstellen ja ein Objekt aber Zeile 1 nicht. Kranke c++ Syntax hin und her, aber gibts da nicht n konkreten Grund für, in diesem Fall?

Oben ging es z.B. darum dass folgender Aufruf nicht den Standardkonstruktor aufruft; Grund: Compiler hält Ausdruck für ne Funktiondeklaration.

C++:
X beta();  // richtig wäre: X beta;



Und hier kann ich mir das nicht so recht erklären, denn:


C++:
X(obj1);    // falsch
X::X(obj1) // richtig



Ansonsten muß ich das so hinnehmen. Ich hab nämich damit angefangen einen Tutor für C++ zu schreiben und da will ich vor allem auch viele Ausnahmen in der Syntax aufnehmen.


Bearbeitung:
Code tags corrected

Dieser Post wurde am 14.08.2005 um 11:18 Uhr von virtual editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: