Du bist nicht angemeldet.

Werbeanzeige

Nimelrian

Alter Hase

  • »Nimelrian« ist der Autor dieses Themas

Beiträge: 1 260

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

1

06.03.2015, 18:39

Wieder das leidige Thema des Operator Overloadings.

Hi zusammen.

Ich implementiere aktuell eine Matrix-Klasse, Teil davon ist das Überladen von (vielen) Operatoren.

Der aktuelle Stand der .hpp ist unten im Post zu sehen (Will den Textfluss nicht unterbrechen).

Wie zu sehen ist, habe ich aktuell alle Operatoren als Non-Member deklariert, muss sie dafür aber als friend der Klasse deklarieren. Grund dafür ist, dass das Array mit den Matrixelementen private ist (Würde ich auch gerne so lassen). Würdet ihr das auch so implementieren wie ich? Wenn nein, wieso nicht?

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
105
106
107
108
109
110
111
112
113
#pragma once
#include <ostream>
#include "Vector2.hpp"
class Matrix2 {
public:
    Matrix2();
    Matrix2(
        float m11, float m12,
        float m21, float m22);

    static const Matrix2 identity;

    bool isAlmostEqual(const Matrix2& mat) const;

private:
    static const std::size_t ENTRIES = 4;

    float _matrix[ENTRIES];


    // Befriend ALL the operators!

    friend std::ostream& operator << (std::ostream& out, const Matrix2& mat);

    friend bool operator == (const Matrix2& lhs, const Matrix2& rhs);
    friend bool operator != (const Matrix2& lhs, const Matrix2& rhs);

    friend Matrix2& operator += (const Matrix2& lhs, const Matrix2& rhs);
    friend Matrix2 operator + (const Matrix2& lhs, const Matrix2& rhs);
    friend Matrix2& operator -= (const Matrix2& lhs, const Matrix2& rhs);
    friend Matrix2 operator - (const Matrix2& lhs, const Matrix2& rhs);

    friend Matrix2 operator - (const Matrix2& lhs);

    friend Matrix2& operator *= (const Matrix2& lhs, const Matrix2& rhs);
    friend Matrix2 operator * (const Matrix2& lhs, const Matrix2& rhs);
    friend Matrix2& operator *= (const Matrix2& lhs, float rhs);
    friend Matrix2 operator * (const Matrix2& lhs, float rhs);
    friend Matrix2 operator * (float lhs, const Matrix2& rhs);

    template <typename T>
    friend Vector2<T>& operator *= (const Vector2<T>& lhs, const Matrix2& rhs);
    template <typename T>
    friend Vector2<T>& operator *= (const Matrix2& lhs, const Vector2<T>& rhs);
    template <typename T>
    friend Vector2<T> operator * (const Vector2<T>& lhs, const Matrix2& rhs);
    template <typename T>
    friend Vector2<T> operator * (const Matrix2& lhs, const Vector2<T>& rhs);
};

///////////////
// Operators //
///////////////

// Streams
std::ostream& operator<<(std::ostream& out, const Matrix2& mat);

// Comparison operators
bool operator == (const Matrix2& lhs, const Matrix2& rhs);
bool operator != (const Matrix2& lhs, const Matrix2& rhs);


// Arithmetics

// Addition with other matrix, assigning result to matrix
Matrix2& operator += (const Matrix2& lhs, const Matrix2& rhs);

// Addition with other matrix
Matrix2 operator + (const Matrix2& lhs, const Matrix2& rhs);

// Subtraction with other matrix, assigning result to matrix
Matrix2& operator -= (const Matrix2& lhs, const Matrix2& rhs);

// Subtraction with other matrix
Matrix2 operator - (const Matrix2& lhs, const Matrix2& rhs);

// Unary (Matrix2 a = -b)
Matrix2 operator - (const Matrix2& lhs);



// Multiplication and division

// Multiplication with other matrix, assigning result to matrix
Matrix2& operator *= (const Matrix2& lhs, const Matrix2& rhs);

// Multiplication with other matrix
Matrix2 operator * (const Matrix2& lhs, const Matrix2& rhs);

// Multiplication with scalar, assigning result to matrix
Matrix2& operator *= (const Matrix2& lhs, float rhs);

// Multiplication with scalar, matrix on left side
Matrix2 operator * (const Matrix2& lhs, float rhs);

// Multiplication with scalar, matrix on right side
Matrix2 operator * (float lhs, const Matrix2& rhs);

// Multiplication with vector, matrix right, assigning result to vector
template <typename T>
Vector2<T>& operator *= (const Vector2<T>& lhs, const Matrix2& rhs);

// Multiplication with vector, matrix left, assigning result to vector
template <typename T>
Vector2<T>& operator *= (const Matrix2& lhs, const Vector2<T>& rhs);

// Multiplication with vector, matrix right
template <typename T>
Vector2<T> operator * (const Vector2<T>& lhs, const Matrix2& rhs);

// Multiplication with vector, matrix right
template <typename T>
Vector2<T> operator * (const Matrix2& lhs, const Vector2<T>& rhs);
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

David Scherfgen

Administrator

Beiträge: 10 334

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

2

06.03.2015, 18:41

Bei Matrizen und Vektoren würde ich die Elemente public machen. Denn die sind ja gerade das, was eine Matrix bzw. einen Vektor ausmacht. Da dann noch Getter und Setter drumherum zu basteln finde ich albern.

Nimelrian

Alter Hase

  • »Nimelrian« ist der Autor dieses Themas

Beiträge: 1 260

Beruf: Softwareentwickler (aktuell Web/Node); Freiberuflicher Google Proxy

  • Private Nachricht senden

3

06.03.2015, 18:47

Hmm, hast Recht. Bei den Vektoren hab ich's ja auch so...

Egtl. versuche ich immer die Dinge private zu halten, soweit es geht, aber hier sind's ja wirklich nur reine Daten.

Danke :)
Ich bin kein UserSideGoogleProxy. Und nein, dieses Forum ist kein UserSideGoogleProxyAbstractFactorySingleton.

4

07.03.2015, 09:31

Egtl. versuche ich immer die Dinge private zu halten, soweit es geht, aber hier sind's ja wirklich nur reine Daten.

Naja, das ist halt so die Regel, die man ganz am Anfang einmal lernt. Aber wichtig ist, dass man irgendwann den Schritt macht zu verstehen, warum sich das empfiehlt, weil man dann die Fälle erkennt, in denen es eigentlich doch keinen Sinn macht.

Ansonsten würde ich dir noch einen Tipp geben. Wenn du schon unbedingt deine eigenen Mathe-Klassen schreiben musst (vermutlich als Übung oder zum Spaß?), dann versuche wenigstens das Speicherlayout den gängigen implementierungen anzupassen. Du hast halt beispielsweise noch die Größe als Wert in jedem Objekt gespeichert.
Der Hintergrund ist ganz einfach der, dass man oft Vektoren oder Matrizen an irgendwelche Grafikschnittstellen übergeben muss. Ist das Layout identisch, kannst du einfach einen Pointer übergeben, und bist fertig. Wenn OpenGL z.B. ein float-Array erwartet, kannst du trotzdem ein Vecotren-Array übergeben, dank identischen Layout mekrt OpenGL davon nichts und du kannst bei dir aber all die erweiterte Funktionalität benutzen. Außerdem bist du damit zu vielen anderen Mathe-Bibliotheken kompatibel und muss die Typen nicht händisch konvertieren.
Die Matrixgröße kannst du zum Beispiel als Template-Parameter speichern. Ist anfangs nicht ganz trivial, aber du kannst dich daran orientieren, wie anderes es machen. Bei eigen oder glm solltest du das z.B. finden können.
Lieber dumm fragen, als dumm bleiben!

David Scherfgen

Administrator

Beiträge: 10 334

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

07.03.2015, 09:37

Du hast halt beispielsweise noch die Größe als Wert in jedem Objekt gespeichert.

Guck nochmal genau hin. Es ist eine statische Konstante, wird also nicht im Objekt gespeichert.

Werbeanzeige