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

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

11

08.02.2011, 15:53

funktionen definiert man in der cpp.
hast viel in Java oder C# entwickelt? du vergisst den speicher für v1, v2 und v3 frei zu geben.
ausserdem ists dort unnötig mit new zu arbeiten.
benutz anstelle von system("pause"); lieber std::cin.get();

edit: vielleicht wäre ein gutes nachschlagewerk was für dich? c++ ist keine sprache die man mal nebenbei lernt.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »NachoMan« (08.02.2011, 15:59)


Sylence

Community-Fossil

Beiträge: 1 663

Beruf: Softwareentwickler

  • Private Nachricht senden

12

08.02.2011, 15:57

Jede cpp wird für sich kompiliert. #include sagt dem compiler (bzw genauer: dem präprozessor), dass er den Dateiinhalt der Datei an die Stelle kopieren soll.
Das heißt am Ende gibt es mehrere riesige cpp Dateien, in denen alle Header als klartext drinstehen. Und dann wird compiliert.

Wenn jetzt aber die definition des operators, in einer anderen cpp Datei liegt (die Dateien wissen nichts voneinander), dann weiß er eben damit nichts anzufangen.

EDIT:
Zu dem neuen Fehler: Du hast jetzt zwei cpp Dateien, in denen beides mal der operator drinsteht.

Im Header deklarieren und in einer cpp (die Vector3.cpp bietet sich hier an ;)) definieren.
Das müsste dann ungefähr so aussehen (ungefähr, weil ich seit ewigkeiten nichts mehr in c++ gemacht hab ^^)

Vektor3D.h

Quellcode

1
Vektor3D operator +(const Vektor3D& left, const Vektor3D& right);


Vektor3D.cpp

Quellcode

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

13

08.02.2011, 16:03

Eine Frage an dot: Warum widersprechen getter- und setter dem Prinzip der Kapselung. Eigentlich haben sie ja den Vorteil, dass man zusätzliche Kontrollen, Zähler, oder anderes (später) dazumachen kann, ohne das interface zu ändern, oder gibt es irgendwelche Nachteile, von denen ich nicht weiß?

dot

Supermoderator

Beiträge: 9 757

Wohnort: Graz

  • Private Nachricht senden

14

08.02.2011, 16:03

Das Problem ist dass du den operator +() nun in deinem Header definiert hast. Das führt dazu dass diese Definition in jedem .cpp File in das der Header inkludiert wird vorkommt. Beim Linken der einzelnen .obj Files findet der Linker dann in jedem .obj File das aus einem .cpp das deinen Header inkludiert hat entstanden ist eine Definition des operator +() was natürlich zuviel ist. Entweder den operator +() inline machen oder die Definition in ein .cpp auslagern.

Eine Frage an dot: Warum widersprechen getter- und setter dem Prinzip der Kapselung.

Naja, was genau verstehst du denn unter Kapselung?

15

08.02.2011, 16:18

Ok dank eurer sehr guten Hilfe habe ich jetzt einiges mehr verstanden und es funktioniert soweit.

hier mal mein Code ... btw ich bin auf englisch umgestiegen.

und wenn ihr was an meinem code zu meckern ahb ich bin dankbar ;)

Vector3D.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
#ifndef VECTOR3D
#define VECTOR3D

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

        void Add(Vector3D& vec);
        void Sub(Vector3D& vec);
        void CrossProduct(Vector3D& vec);
        double DotProduct(Vector3D& vec);
        void Scale(double value);
};

Vector3D operator +(const Vector3D& left, const Vector3D& right);

#endif


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


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

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

Vector3D::~Vector3D(){
}

void Vector3D::Add(Vector3D& vec){
    x+=vec.x; y+=vec.y; z+=vec.z;
}

void Vector3D::Sub(Vector3D& vec){
    x-=vec.x; y-=vec.y; z-=vec.z;
}

void Vector3D::CrossProduct(Vector3D& vec){
    x = y*vec.z-z*vec.y;
    y = z*vec.x-x*vec.z;
    z = x*vec.y-y*vec.x;
}

double Vector3D::DotProduct(Vector3D& vec){
    return x*vec.x+y*vec.y+z*vec.z;
}

void Vector3D::Scale(double value){
    x *= value;
    y *= value;
    z *= value;
}
Vector3D operator +(const Vector3D& left, const Vector3D& right)
{
    return Vector3D(left.x + right.x, left.y + right.y, left.z + right.z);
}


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
36
37
38
39
#include "stdafx.h"
#include <iostream>
#include "Vector3D.h"

using namespace std;


int _tmain(int argc, _TCHAR* argv[])
{
    Vector3D *v1 = new Vector3D();
    Vector3D *v2 = new Vector3D(1.0, 2.0, 3.0);
    Vector3D *v3 = new Vector3D(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;

    Vector3D v4;
    Vector3D v5(1.0, 2.0, 3.0);
    Vector3D 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;

    delete(v1);
    delete(v2);
    delete(v3);

    std::cin.get(); 

    return 0;
}


dann amch ich mich mal an die anderen operatoren :P

NachoMan

Community-Fossil

Beiträge: 3 885

Wohnort: Berlin

Beruf: (Nachhilfe)Lehrer (Mathematik, C++, Java, C#)

  • Private Nachricht senden

16

08.02.2011, 16:23

du könntest aus deiner vectorklasse eine templateklasse machen und die anfangsbuchstaben der methoden klein schreiben. zu meckern gibts in meinen augen nichts mehr.
"Der erste Trunk aus dem Becher der Erkenntnis macht einem zum Atheist, doch auf dem Grund des Bechers wartet Gott." - Werner Heisenberg
Biete Privatunterricht in Berlin und Online.
Kommt jemand mit Nach oMan?

17

08.02.2011, 16:38

Mhh joa methoden namen hab ich in java immer klein
aber hab mir paar codes zu CPP angeschaut und da waren die immer groß da habe ich ich angenommen das sei so konvention :P

wie mache ich das mit mit dem += da will ich ja das entsprechende element bearbeiten. Also mach ich das als member variable?

Also is jetzt nur ne anahme ich probiers erstmal ...

Fred

Supermoderator

Beiträge: 2 121

Beruf: Softwareentwickler

  • Private Nachricht senden

18

08.02.2011, 16:54

Konvention ist, was du oder dein Team vorschreiben ;).
Ja += solltest du als Member-Funktion überladen. Da solltest du dann entsprechend auch das Objekt, das links von += steht, verändern. Aber dot hat das weiter oben schon mal gezeigt, wie es aussehen sollte.

19

08.02.2011, 17:47

ahh ok danke. Scheint soweit alles zu funktionieren.

Hier meine Lösung:

Vector3D.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
25
26
27
28
29
30
31
32
33
#ifndef VECTOR3D
#define VECTOR3D

class Vector3D
{
    public:
        double x,y,z; // dimensions of R3
        
        //constructors and destructor
        Vector3D();
        Vector3D(double x, double y, double z);
        ~Vector3D();

        //Memberfunctions
        void Set(double x, double y, double z); 
        void Add(Vector3D& vec); 
        void Sub(Vector3D& vec);
        void CrossProduct(Vector3D& vec);
        double DotProduct(Vector3D& vec);
        void Scale(double value);

        Vector3D& operator +=(const Vector3D& vec);
        Vector3D& operator -=(const Vector3D& vec);
        Vector3D& operator *=(const Vector3D& vec);

};

//overloaded Operators
Vector3D operator +(const Vector3D& left, const Vector3D& right);
Vector3D operator -(const Vector3D& left, const Vector3D& right);
Vector3D operator *(const Vector3D& left, const Vector3D& right);

#endif


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

// ------------------- Constructor -------------------------
Vector3D::Vector3D()
  : x(0.0), y(0.0), z(0.0)
{
}


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

// ------------------- Destructor ----------------------------
Vector3D::~Vector3D(){
}

// ------------------- Memberfunctions-----------------------
void Vector3D::Set(double x, double y, double z){
    this->x+=x; this->y+=y; this->z+=z;
}

void Vector3D::Add(Vector3D& vec){
    x+=vec.x; y+=vec.y; z+=vec.z;
}

void Vector3D::Sub(Vector3D& vec){
    x-=vec.x; y-=vec.y; z-=vec.z;
}

void Vector3D::CrossProduct(Vector3D& vec){
    double tmpX = x, tmpY = y, tmpZ = z;  
    x = tmpY*vec.z-tmpZ*vec.y;
    y = tmpZ*vec.x-tmpX*vec.z;
    z = tmpX*vec.y-tmpY*vec.x;
}

double Vector3D::DotProduct(Vector3D& vec){
    return x*vec.x+y*vec.y+z*vec.z;
}

void Vector3D::Scale(double value){
    x *= value; y *= value; z *= value;
}

Vector3D& Vector3D::operator +=(const Vector3D& vec) 
{
  x += vec.x; y += vec.y; z += vec.z;
  return *this;
}

Vector3D& Vector3D::operator -=(const Vector3D& vec) 
{
  x -= vec.x; y -= vec.y; z -= vec.z;
  return *this;
}

Vector3D& Vector3D::operator *=(const Vector3D& vec) 
{
  Vector3D tmp = vec;
  CrossProduct(tmp);
  return *this;
}


// ------------------- more Overlaoded operators -----------------------

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

Vector3D operator -(const Vector3D& left, const Vector3D& right)
{
    return Vector3D(left.x - right.x, left.y - right.y, left.z - right.z);
}

Vector3D operator *(const Vector3D& left, const Vector3D& right) 
{
    Vector3D tmp = left;
    Vector3D tmp2 = right;
    tmp.CrossProduct(tmp2);
    return tmp;
}


Testprogramm:

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

using namespace std;

/** Hauptprogramm.

    zum Testen der Klasse Vector3D
*/


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

    
    *v3 = *v1 + *v2;

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

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

    
    v6 = v4 + v5;

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

    v6 = v5 - v4; 

    cout << "V5-V4: " << v6.x << " " << v6.y << " " << v6.z << endl;

    v5 += v4; 

    cout << "V5+=V4: " << v5.x << " " << v5.y << " " << v5.z << endl;

    v5 -= v4; 

    cout << "V5-=V4: " << v5.x << " " << v5.y << " " << v5.z << endl;

    v6 = *v1**v2; 

    cout << "V1*V2: " << v6.x << " " << v6.y << " " << v6.z << endl;

    *v1*=*v2; 

    cout << "V1*=V2: " << v1->x << " " << v1->y << " " << v1->z << endl;

    delete(v1);
    delete(v2);
    delete(v3);

    std::cin.get(); 

    return 0;
}


Danke an alle die mir geholfen haben, ihr wart sehr hilfreich.

20

08.02.2011, 21:18

Objektive Kritik:

Die Methoden Add, Sub, CrossProduct und DotProduct verstoßen gegen die const-correctness. Ein Zuweisungsoperator sollte noch rein.

Subjektive Kritik:


  • Die Methode Set ist überflüssig. Man kann das Objekt auch gleich neu anlegen.
  • Die Methoden Add, Sub sind überflüssig, weil ebenfalls als Operatoren definiert.
  • Die Methode CrossProduct ist eher ein "Schwergewicht" und sollte als freie Funktion definiert werden. Genau genommen wird beim Berechnen des Kreuzproduktes eine (temporäre) Kopie des ursprünglichen Vektors erstellt. Dieses Verhalten zeigen globale Operator-Funktionen immer.
  • (Die Methode DotProduct könnte daher aus dem Blickpunkt eines möglichst stringenten Interfaces auch frei definiert werden.)
  • Die freien Operator-Funktionen sollten auf die breits definierten Operator-Methoden zugreifen (mit CrossProduct wird das in einem Falle ja bereits getan). Es ist in Allgemeinen eine gute Praxis, die globalen Operator-Funktionen die Operator-Methoden der entsprechenden Klasse verwenden zu lassen. Das verhindert doppelten Code und ggf. Fehler, die beim "kopieren" entstehen können.
So, dass soll aber auch reichen ;) .

Grüße aus dem Sauerland ...

bwbg

EDIT: Ich habe eine Template-Klasse für eben diese Vektoren aus meinen Archiven ausbuddeln können. Nie sehr ästhetisch, aber zum "Nachlesen" durchaus brauchbar. Das Test-Programm habe ich gerade dazu gehackt.

Zitat

Ich bin nicht der Messias.
Ich sage, du bist es, Herr. Und ich muss es wissen, denn ich bin schon einigen gefolgt.

https://bitbucket.org/bwbg

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »bwbg« (08.02.2011, 21:26)


Werbeanzeige