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

08.02.2011, 13:16

[C++] Problem: Operatoren für eine Klasse überladen

Hallo Community,

ich wollte mal meine CPP-Kentnisse auffrischen und habe gemerkt... ich kann eigtl nix mehr. Also habt ein Nachsehen falls ich Neulingsfragen stelle :P.

Vorweg:
Betriebssystem: Windows 7 64bit
Entwicklungsumgebung: Microsoft Visual C++ 2010 Express

Es geht um folgendes:
Ich wollte mir eine Klasse für Vektoren im R³ erstellen. Einfach nochma schaun wie das so mit Klassen war.
Vektoren lassen sich ja auch mit einem Wert skalieren, das Vektor- und Skalarprodukt kann man bilden, und sie lassen sich addierden oder subtrahieren.
Das Addieren und Subtrahieren wollte ich nun so realisieren dass ich zur Klasse Vektor3D die intanzen v1, v2 und v3 habe. Für die ich schreiben kann v1 = v2 + v3;

Das Problem:

Wenn ich meine Instanzen auf dem stack erzeuge klappt das alles wunderbar.
Sobald ich aber den Heap benutze meckert der rum

EDIT: Problem gelöst ... Lösung seht ihr hier

Quellcodes:

Vektor3D.h

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
#ifndef VEKTOR3D
#define VEKTOR3D

class Vektor3D
{
private:
double x,y,z;
public:
Vektor3D();
Vektor3D(double x, double y, double z);
~Vektor3D();

double GetX();
double GetY();
double GetZ();

void SetX(double x);
void SetY(double y);
void SetZ(double z);

Vektor3D operator+(Vektor3D vec);
};

#endif


Vektor3D.cpp

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
#include "stdafx.h"
#include "Vektor3D.h"

Vektor3D::Vektor3D(){
x = 0;
y = 0;
z = 0;
}

Vektor3D::Vektor3D(double x, double y, double z){
this->x = x;
this->y = y;
this->z = z;
}

double Vektor3D::GetX(){
return x;
}

double Vektor3D::GetY(){
return y;
}

double Vektor3D::GetZ(){
return z;
}

void Vektor3D::SetX(double x){
this->x = x;
}

void Vektor3D::SetY(double y){
this->y = y;
}

void Vektor3D::SetZ(double z){
this->z = z;
}

Vektor3D Vektor3D::operator+(Vektor3D vec){
x += vec.GetX();
y += vec.GetY();
z += vec.GetZ();
return *this;
}


Vektor3D::~Vektor3D(){
}


Hauptprogramm

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include "stdafx.h"
#include <iostream>
#include "Vektor3D.h"

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
Vektor3D *v1 = new Vektor3D();
Vektor3D *v2 = new Vektor3D(1.0, 2.0, 3.0);
Vektor3D *v3 = new Vektor3D(1.0, 1.0, 1.0);

v1 = v2 + v3; // <-- Hier is v3 rot unterstrichen und mir wird gesagt... "Error: der Ausdruck muss einen Integralen Typ oder einen Enumerationstyp aufweisen".

system("Pause");
return 0;
}


ich hoffe ihr könnt mir helfen.
Hab irgendwie im hinterkopf dass man objekte lieber aufm heap erzeugen sollte.

Und wenn einer mir sagt, wie ich das für den += Operator mache, wäre ich auch sehr dankbar.

mit freundlichen Grüßen
Florian Weinhold

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »vanillebaerchen« (09.02.2011, 00:20)


dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

2

08.02.2011, 13:35

v1, v2, und v3 sind Pointer, klar dass er rummeckert:

C-/C++-Quelltext

1
*v1 = *v2 + *v3;

;)

Dein operator + verändert übrigens ein Objekt, was er wohl nicht sollte. Nach obiger Zeile hat v2 ebenfalls den Wert der Summe und nichtmehr den Wert den es davor hatte...

Besser so:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
Vektor3D& operator +=(const Vektor3D& vec) // Memberfunktion
{
  x += vec.GetX();
  y += vec.GetY();
  z += vec.GetZ();
  return *this;
}

Vektor3D operator +(const Vektor3D& a, const Vektor3D& a) // keine Memberfunktion
{
  return Vektor3D(a.GetX() + b.GetX(), a.GetY() + b.GetY(), a.GetZ() + b.GetZ());
}


Ich würd mir außerdem nochmal überlegen ob es für die Koordinaten wirklich getter und setter braucht. Imo is das eher unnötig...

Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von »dot« (08.02.2011, 13:45)


3

08.02.2011, 13:48

ahh cool danke für die schnelle Antwort.

Hätte ich acuh selber drauf kommen können ^^. Naja ich mag zeiger nicht.

Und das mit den gettern und settern habe ich mir aus Java von meinem Prof. angewöhnt, der meint immer alles was geht kapseln.

Naja ersma schaun obs dann auch so geht :)

danke nochma ich saß da schon über na stunde dran.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

4

08.02.2011, 13:49

Und das mit den gettern und settern habe ich mir aus Java von meinem Prof. angewöhnt, der meint immer alles was geht kapseln.

getter und setter widersprechen dem Prinzip der Kapselung und sind erfahrungsgemäß ein Symptom von schlechtem Design ;)

5

08.02.2011, 14:04

ok dann will ich mich mal belehren lassen ^^.

habs mal mit einer nicht memberfunktion versucht

headerfile:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#ifndef VEKTOR3D
#define VEKTOR3D

class Vektor3D
{
    public:
        double x,y,z;
        Vektor3D();
        Vektor3D(double x, double y, double z);
        ~Vektor3D();

};

#endif


cpp

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
#include "stdafx.h"
#include "Vektor3D.h"

Vektor3D::Vektor3D(){
    x = 0;
    y = 0;
    z = 0;
}

Vektor3D::Vektor3D(double x, double y, double z){
    this->x = x;
    this->y = y;
    this->z = z;
}

Vektor3D::~Vektor3D(){
}

Vektor3D operator +(const Vektor3D left, const Vektor3D right)
{
    return Vektor3D(left.x + right.x, left.y + right.y, left.z + right.z);
}


main

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "stdafx.h"
#include <iostream>
#include "Vektor3D.h"

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
    Vektor3D *v1 = new Vektor3D();
    Vektor3D *v2 = new Vektor3D(1.0, 2.0, 3.0);
    Vektor3D *v3 = new Vektor3D(1.0, 1.0, 1.0);

    
    *v1 = *v2 + *v3;

    system("Pause");
    return 0;
}


jetzt meckert der aber rum, dass kein operand dafür vorhanden ist.

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

6

08.02.2011, 14:09

ok dann will ich mich mal belehren lassen ^^.

Naja, wenn man kurz drüber nachdenkt ist das eigentlich eh klar, was ist denn das Prinzip der Kapselung?

jetzt meckert der aber rum, dass kein operand dafür vorhanden ist.

Was ist denn die genaue Fehlermeldung? Abgesehen davon würde ich dazu raten die Parameter des operator + als Referenz und nicht als Wert zu übergeben (wenn dus nicht als Referenz machst ist das const nicht wirklich notwendig btw).

Und, auch wenns im konkreten Beispiel keinen wirklichen Unterschied macht, in C++ verwendet man eine Initialisierungsliste um Member zu Initialisieren:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
Vektor3D::Vektor3D()
  : x(0.0), y(0.0), z(0.0)
{
}

Vektor3D::Vektor3D(double x, double y, double z)
  : x(x), y(y), z(z)
{
}

7

08.02.2011, 14:17

Ok const is weg und initialisierungsliste ist drin.
(danke kannte ich net mit der liste)

und hier das sagt der mir jetzt


(Link)


edit:

C-/C++-Quelltext

1
2
3
4
Vektor3D operator +(Vektor3D& left, Vektor3D& right)
{
    return Vektor3D(left.x + right.x, left.y + right.y, left.z + right.z);
}


nochmal edit:

da ich es jetzt doch als referenz hab... muss das const wieder rein?

Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

8

08.02.2011, 14:29

Du musst den operator auch in einen header stecken ;)

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

9

08.02.2011, 14:30

Naja, das ist aber nur eine Fehlermeldung von IntelliSense, das bedeutet nicht dass es nicht kompiliert...

da ich es jetzt doch als referenz hab... muss das const wieder rein?

Naja, "muss" nicht aber es wäre sinnvoll. Der Grund warum man hier eine Referenz übergibt ist einfach um ein Kopieren der Operanden zu sparen. Mit dem const drückt man aus dass man nicht vorhat die Operanden zu verändern.

Du musst den operator auch in einen header stecken ;)

Das stimmt natürlich, ich ging davon aus dass ihm das klar ist ^^ , aber das kann natürlich ein Grund für den Fehler sein...

10

08.02.2011, 15:39

ok nö wusste ich net. Könnt ihr auch sagen warum ... bin halbwegs wissbegierig.
ich hatte vor 3 semestern ma c++. Hab aber nur halbherzig zugehört ... so gelernt dass es für ne 1.3 reichte und dann wieder alles vergessen. Aber da war ich noch so drauf dass ich ersma bestehen will. Jetzt bin ich alles nebenbei am nachholen und auch begierig drauf es zu wissen.

und ja jetzt wo es in der header file steht kommt net mehr dieses meldung


ok hier nochmal alles wie ichs jetzt habe:

Vektor3D.h

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#ifndef VEKTOR3D
#define VEKTOR3D

class Vektor3D
{
    public:
        double x,y,z;
        Vektor3D();
        Vektor3D(double x, double y, double z);
        ~Vektor3D();

};

Vektor3D operator +(const Vektor3D& left, const Vektor3D& right)
{
    return Vektor3D(left.x + right.x, left.y + right.y, left.z + right.z);
}
#endif


Vektor.ccp

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "stdafx.h"
#include "Vektor3D.h"


Vektor3D::Vektor3D()
  : x(0.0), y(0.0), z(0.0)
{
}

Vektor3D::Vektor3D(double x, double y, double z)
  : x(x), y(y), z(z)
{
}

Vektor3D::~Vektor3D(){
}


Hauptprogramm

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
#include "stdafx.h"
#include <iostream>
#include "Vektor3D.h"

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
    Vektor3D *v1 = new Vektor3D();
    Vektor3D *v2 = new Vektor3D(1.0, 2.0, 3.0);
    Vektor3D *v3 = new Vektor3D(1.0, 1.0, 1.0);

    
    *v1 = *v2 + *v3;

    cout << "V1: " << v1->x << " " << v1->y << " " << v1->z << endl;
    cout << "V2: " << v2->x << " " << v2->y << " " << v2->z << endl;
    cout << "V3: " << v3->x << " " << v3->y << " " << v3->z << endl;

    Vektor3D v4;
    Vektor3D v5(1.0, 2.0, 3.0);
    Vektor3D v6(1.0, 1.0, 1.0);

    
    v4 = v5 + v6;

    cout << "V4: " << v4.x << " " << v4.y << " " << v4.z << endl;
    cout << "V5: " << v5.x << " " << v5.y << " " << v5.z << endl;
    cout << "V6: " << v6.x << " " << v6.y << " " << v6.z << endl;


    system("Pause");
    return 0;
}


jetzt kommt ne meldung beim kompilieren

1>Vektor3D.obj : error LNK2005: "class Vektor3D __cdecl operator+(class Vektor3D const &,class Vektor3D const &)" (??H@YA?AVVektor3D@@ABV0@0@Z) ist bereits in PhysikEngine.obj definiert.
1>C:\Users\Vanillebaer\Documents\Visual Studio 2010\Projects\PhysikEngine\Debug\PhysikEngine.exe : fatal error LNK1169: Mindestens ein mehrfach definiertes Symbol gefunden.

ich weiss net genau was ich damit anfangen soll, aber für mich heisst das ... ich habe die methode angeblich schon irgendwo drin

Werbeanzeige