Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

14.03.2011, 14:20

Kopierkonstruktor verständnisproblem

Hallo liebe Programmierer-Gemeinschaft,

ich hab in C++ mal eine "längere" Pause gemacht ca. 1,5 Wochen. Jetzt hab ich mit dem nächsten Thema des Buches weitergemacht dem Kopierkonstruktor... Warum man ihn verwended verstehe ich schon, darin liegt nicht das Problem. Eher wie man ihn erzeugt... In dem Buch wird das ja wie folgt gemacht:

C-/C++-Quelltext

1
2
3
4
5
6
7
CJaeger::CJaeger (const CJaeger &rhs)
{
cout << "Kopierkonstruktor wurde aufgerufen" << endl;

m_pGeschwindigkeit = new int;
*m_pGeschwindigkeit =  *(rhs.m_pGeschwindigkeit);
}


Im Buch steht dann das erst mal eine Meldung aufgerufen wird wenn der Kopierkostruktor gebraucht wird und danach das die Referenz rhs jetzt auf unsere Originalinstanz verweist... Ich Frage mich nur, warum?
Hab ich irgendwas vergessen oder übersehen?

Vielen Dank schon mal für eure Antworten!

bennichamp :)

Nox

Supermoderator

Beiträge: 5 272

Beruf: Student

  • Private Nachricht senden

2

14.03.2011, 14:34

Ich muss ehrlich sagen, dass ich deine Frage nicht ganz verstehe, aber als kurzes Beispiel:

C-/C++-Quelltext

1
2
CJaeger jaeger1;
CJaeger jaeger2(jaeger1);//<-hier wird explizit der copy-ctor aufgerufen; rhs wird also das objekt jaeger1 sein und "this" ist dann jaeger2 (innerhalb deines copy-ctors).

Ggf. klärt das ja schon irgendwie deine Frage. Falls nicht versuch sie bitte nochmal ein wenig zu erläutern.
PRO Lernkurs "Wie benutze ich eine Doku richtig"!
CONTRA lasst mal die anderen machen!
networklibbenc - Netzwerklibs im Vergleich | syncsys - Netzwerk lib (MMO-ready) | Schleichfahrt Remake | Firegalaxy | Sammelsurium rund um FPGA&Co.

3

14.03.2011, 15:21

Sorry, aber ich verstehe dein Beispiel geradfe nicht :S

Ich hab hier nochmal den gleichen Quelltext aber als ganzes und nicht als Auschnitt:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// C++ für Spieleprogrammierer
// Listing 11.7
// Der Kopierkonstruktor
//
#include <iostream>

using namespace std;

// Klassen
//

// Klasse für ein Raumschiff
//
class CRaumschiff
{
    public:
        CRaumschiff ();
        ~CRaumschiff ();
        CRaumschiff (const CRaumschiff &rhs);

        void ZeigeWerte ();

    private:
        int *m_pGeschwindigkeit;

};

// Konstruktor
//
CRaumschiff::CRaumschiff ()
{
    cout << "Konstruktor wurde aufgerufen.\n";
    // Speicher reservieren
    //
    m_pGeschwindigkeit = new int;
    * m_pGeschwindigkeit = 1541;

} // Konstruktor

// Destruktor
//
CRaumschiff::~CRaumschiff ()
{
    cout << "Destruktor wurde aufgerufen.\n";
    // Wenn pGeschwindigkeit ein gültiger Zeiger ist,
    // Speicher wieder freigeben.
    //
    if (m_pGeschwindigkeit != NULL)
    {
        delete (m_pGeschwindigkeit);
        m_pGeschwindigkeit = NULL;
    }

} // Destruktor

// Kopierkonstruktor
CRaumschiff::CRaumschiff (const CRaumschiff &rhs)
{
    cout << "Kopierkonstruktor wurde aufgerufen.";
    cout << endl;

    // Tiefe Kopie
    m_pGeschwindigkeit = new int;
    *m_pGeschwindigkeit = *(rhs.m_pGeschwindigkeit);

} // Kopierkonstruktor

// ZeigeWerte
//
void CRaumschiff::ZeigeWerte ()
{
    // Wenn der Zeiger gültig ist, Geschwindigkeit anzeigen
    //
    if (m_pGeschwindigkeit != NULL)
    {
        cout << "Geschwindigkeit: " << * m_pGeschwindigkeit;
        cout << endl;
    }

} // ZeigeWerte

// Eine beliebige Funktion, die eine Instanz
// der Klasse CRaumschiff übernimmt
void Funktion (CRaumschiff Schiff)
{
    Schiff.ZeigeWerte ();

} // Funktion

// Hauptprogramm
//
int main ()
{
    // Ein neues Raumschiff erzeugen
    CRaumschiff Jaeger;
    
    // Geschwindigkeit des Raumschiffs anzeigen lassen
    Jaeger.ZeigeWerte ();

    // Die Instanz an eine Funktion übergeben
    Funktion (Jaeger);

    return (0);
}


Anstatt CJaeger heißt ddie Klasse jetzt CRaumschiff :whistling:

Ich gehe jetzt mal den Quelltext so durch wie ich ihn verstehe...

In der main Funktion wird eine Instanz dert Klasse CRaumschiff erstellt und für den Zeiger *p_mGeschwindigkeit Speicher für einen int-Wert reserviert. Anschließend wird der Speicher mit dem Wert 1514 "gefüllt".
Als nächstes wird einfach die Memberfunktion "Zeige Werte" der Raumschiff-Klasse aufgerufen um die Geschwindigkeit auf dem Bildschirm auszugeben...
Dann wird die Funktion "Funktion" aufgerufen die die Jaeger-Instanz übernimmt und in der Funktion wieder die "Zeige Werte" Memberfunktion ausführt.

Wenn jetzt die Funktion "Funktion" ausgeführt wird, wird ja automatisch der Kopierkonstruktor ausgeführt, welcher eine Konstante Referenz der Raumschiffklasse (in diesem Fall rhs) übernimmt. Und ab hier stehe ich irgendwie im Dunkeln... Ich glaube zwar dass, das passiert aber bin mir nicht ganz sicher: Für den Zeiger p_mGeschwindigkeit wird nochmals neuer Speicher reserviert. Dann wird dem Speicher der Wert zugewiesen der im Speicher der Zeigers rhs.m_pGeschwindigkeit steht (sry wenn ich das jetzt falsch ausdrücke aber ich bin mir grade nicht ganz so sicher wie ich das sagen soll). Allerdings haben wir der Membervariablen von der Instzanz rhs nie einen Wert zugewiesen wesshalb der Wert irgendeiner sein könnte oder ?(...

Ich hoffe ihr versteht das aber ich weiß Momentan einfach nicht wie ich es anders ausdrücken soll :wacko:

bennichamp :)

Werwofl

Treue Seele

Beiträge: 100

Beruf: Fachinformatiker für Anwendungsentwicklung

  • Private Nachricht senden

4

14.03.2011, 15:47

Mach dich nicht verrückt. Ist eigentlich ganz einfach:

Ein Kopierkonstruktor ist dazu da, ein bereits bestehendes Obejekt zu kopieren. In deinem Fall erzeugst du den "Jäger". Der Jäger ist vom Typ CRaumschiff.
Das heißt du rufst für die Erzeugung des Jägers den Default-Konstruktor auf. Der Default-Konstruktor ist der Konstruktor der keine Parameter übergeben bekommt, also bei dir CRaumschiff().

Du legst Speicher für die Geschwingkeit an und initialisierst die Geschwindigkeit von deinem Jäger im Default-Konsturktor mit 1541(Das Attribut m_pGeschwindigkeit).

Jetzt schau dir mal den Kopier-Konstruktor an.
Im Grunde sagst du ihm wenn du ein neues Objekt erzeugst: "Hey nimm die Geschwindigkeit vom Jäger aus dem Speicher, aber leg dir eigenen Speicher an damit du nicht zusammen mit dem Jäger langsamer wirst".


Das heißt im main kannst du sagen:

C-/C++-Quelltext

1
2
3
4
5
6
7
int main(){
CRaumschiff Jaeger; //Default-Konstruktor benutzen
CRaumschiff Sammler(Jaeger); //Kopier Konstruktor

funktion(Jaeger);//Zeige Werte von Jaeger
funktion(Sammler);// Zeiger Werte von Sammler
}


Ausgabe sieht natürlich gleich aus. Du heißt den Sammler ja nur kopiert ;)

5

14.03.2011, 15:52

Jetzt hats *klick* gemacht ;)
Vielen Dank für deine Hilfe :thumbsup:
Jetzt wird mir auch das besipiel von nox klar :D

Vielen Dank noch mal

bennichamp :) :)

Werbeanzeige