Sauber Klasse?
-
Hi,
ich werde mich demnächst bei diversen Softwaredevelopment firmen bewerben, die sich auf dem Gebiet Vectorengrafik und 3D Grafik spezialisiert habe. Da die nicht nur auf das äußere gucken (Also nur das was sie sehen) sondern auch auf das Innere, nämlich den Sourcecode, möchte ich ein Ansprechendes, funktionales und gut Durchdachtes Konzept vorlegen.
Als Basis poste ich mal meine vector klasse und hoffe ihr könnt sie verbessern bzw. konstruktiv kritisieren.
class vector { public: union { struct // Unnamed structs, ist illegal, ich weis { float x; float y; float z; float w; }; float values[4]; }; // Constructors vector (void); vector (const vector &other); vector (float x, float y, float z, float w=1.0f); vector (const float (&value)[4]); vector (float value); // Destructors ~vector (void); void clear (void); void random (float min, float max); void negate (void); float length (void); float lengthSqr (void); float angleWith (const vector &other); float distance (const vector &other); float distance (const float (&value)[4]); float distanceSqr (const vector &other); float distanceSqr (const float (&value)[4]); vector normalize (void); float dotProduct (const vector &other); float dotProduct (const float (&value)[4]); vector crossProduct (const vector &other); vector crossProduct (const float (&value)[4]); // Vergleichsoperatoren bool operator == (const vector &other); bool operator != (const vector &other); bool operator == (const float (&value)[4]); bool operator != (const float (&value)[4]); bool operator == (float value); bool operator != (float value); // Grundlegende Operatoren void operator = (const vector &other); void operator = (const float (&value)[4]); void operator = (float value); vector operator - (void) const; vector operator + (const vector &other) const; vector operator - (const vector &other) const; vector operator * (const vector &other) const; vector operator / (const vector &other) const; vector operator + (const float (&value)[4]) const; vector operator - (const float (&value)[4]) const; vector operator * (const float (&value)[4]) const; vector operator / (const float (&value)[4]) const; vector operator + (float value) const; vector operator - (float value) const; vector operator * (float value) const; vector operator / (float value) const; vector& operator += (const vector &other); vector& operator -= (const vector &other); vector& operator *= (const vector &other); vector& operator /= (const vector &other); vector& operator += (const float (&value)[4]); vector& operator -= (const float (&value)[4]); vector& operator *= (const float (&value)[4]); vector& operator /= (const float (&value)[4]); vector& operator += (float value); vector& operator -= (float value); vector& operator *= (float value); vector& operator /= (float value); // Spezial Operatoren und Funktionen // vector operator * (const matrix &_matrix) const; // vector-matrix product // float operator * (const vector &other) const; // dot product // quaternion operator * (const quaternion &_quaternion) const; // vector * quaternion private: }; // .................................................. // /////////////////////////////////////////////////////////////////////////// // Datei: vector.cpp // /////////////////////////////////////////////////////////////////////////// // Autor: Patrick Ullmann // Erstellt: 12.08.2004 // Änderungen: 12.08.2004 (Patrick) Datei erstellt // /////////////////////////////////////////////////////////////////////////// // Beschreibung: Ein 4D Vector der LokiEngine // I N C L U D E S /////////////////////////////////////////////////////////// #include "LokiMath.h" // G L O B A L E S /////////////////////////////////////////////////////////// namespace loki { extern bool g_useSSE; } // F U N K T I O N E N /////////////////////////////////////////////////////// namespace loki { vector::vector (void) : x(0.0f), y(0.0f), z(0.0f), w(1.0f) { } vector::vector (const vector &other) : x(other.x), y(other.y), z(other.z), w(other.w) { } vector::vector (float _x, float _y, float _z, float _w) : x(_x), y(_y), z(_z), w(_w) { } vector::vector (const float (&value)[4]) : x(value[0]), y(value[1]), z(value[2]), w(value[3]) { } vector::vector (float value) : x(value), y(value), z(value), w(value) { } vector::~vector (void) { } void vector::clear (void) { (*this).x = (*this).y = (*this).z = 0.0f; (*this).w = 1.0f; } void vector::random (float min, float max) { (*this).x = min + (static_cast<float>(rand()) / RAND_MAX) * (max - min); (*this).y = min + (static_cast<float>(rand()) / RAND_MAX) * (max - min); (*this).z = min + (static_cast<float>(rand()) / RAND_MAX) * (max - min); (*this).w = min + (static_cast<float>(rand()) / RAND_MAX) * (max - min); } void vector::negate (void) { (*this).x = -(*this).x; (*this).y = -(*this).y; (*this).z = -(*this).z; // (*this).w = -(*this).w; // W wird nicht mit einbezogen. } float vector::length (void) { const float result = 0; (*this).w = 0.0f; __asm { mov esi, this movups xmm0, [esi] mulps xmm0, xmm0 movaps xmm1, xmm0 shufps xmm1, xmm1, 4Eh addps xmm0, xmm1 movaps xmm1, xmm0 shufps xmm1, xmm1, 11h addps xmm0, xmm1 sqrtss xmm0, xmm0 movss result, xmm0 } (*this).w = 1.0f; return (result); } float vector::lengthSqr (void) { return ((*this).x*(*this).x + (*this).y*(*this).y + (*this).z*(*this).z); } float vector::angleWith (const vector &other) { // return (::acosf(((*this)*other) / ((*this).length()*other.length()))); return 0; } float vector::distance (const vector &other) { return (((*this) - other).length()); } float vector::distance (const float (&value)[4]) { return (((*this) - vector(value)).length()); } float vector::distanceSqr (const vector &other) { return (((*this) - other).lengthSqr()); } float vector::distanceSqr (const float (&value)[4]) { return (((*this) - vector(value)).lengthSqr()); } vector vector::normalize (void) { vector ret ((*this)); float f = (*this).length(); if (f != 0.0f) { ret/=f; } return ret; } float vector::dotProduct (const vector &other) { return (other.x*(*this).x + other.y*(*this).y + other.z*(*this).z); } float vector::dotProduct (const float (&value)[4]) { return (value[0]*(*this).x +value[1]*(*this).y + value[2]*(*this).z); } vector vector::crossProduct (const vector &other) { vector result; __asm { mov esi, this mov edi, other movups xmm0, [esi] movups xmm1, [edi] movaps xmm2, xmm0 movaps xmm3, xmm1 shufps xmm0, xmm0, 0xC9 shufps xmm1, xmm1, 0xD2 mulps xmm0, xmm1 shufps xmm2, xmm2, 0xD2 shufps xmm3, xmm3, 0xC9 mulps xmm2, xmm3 subps xmm0, xmm2 mov esi, result movups [esi], xmm0 } w = 1.0f; return (result); } vector vector::crossProduct (const float (&value)[4]) { return ((*this).crossProduct (vector(value))); } // /////////////////////////////////////////////////////////////////////////// // O P E R A T O R E N ####################################################### // /////////////////////////////////////////////////////////////////////////// bool vector::operator == (const vector &other) { for (int i=0; i<4; ++i) { if ((*this).values[i] != other.values[i]) return (false); } return (true); } bool vector::operator == (const float (&value)[4]) { return ((*this) == vector(value)); } bool vector::operator == (float value) { return ((*this) == vector(value)); } bool vector::operator != (const vector &other) { return (!((*this) == other)); } bool vector::operator != (const float (&value)[4]) { return (!((*this) == vector(value))); } bool vector::operator != (float value) { return (!((*this) == vector(value))); } void vector::operator = (const vector &other) { (*this).x = other.x; (*this).y = other.y; (*this).z = other.z; (*this).w = other.w; } void vector::operator = (const float (&value)[4]) { (*this).x = value[0]; (*this).y = value[1]; (*this).z = value[2]; (*this).w = value[3]; } void vector::operator = (float value) { (*this).x = value; (*this).y = value; (*this).z = value; (*this).w = value; } vector vector::operator - (void) const { return vector(-(*this).x,-(*this).y,-(*this).z); } vector vector::operator+ (const vector& other) const { return (vector ((*this).x + other.x, (*this).y + other.y, (*this).z + other.z)); } vector vector::operator- (const vector& other) const { return (vector ((*this).x - other.x, (*this).y - other.y, (*this).z - other.z)); } vector vector::operator* (const vector &other) const { return (vector ((*this).x * other.x, (*this).y * other.y, (*this).z * other.z)); } vector vector::operator/ (const vector &other) const { assert ((other.x != 0.0f) && (other.y != 0.0f) && (other.z != 0.0f)); return (vector ((*this).x / other.x, (*this).y / other.y, (*this).z / other.z)); } vector vector::operator+ (const float (&value)[4]) const { return (vector ((*this).x + value[0], (*this).y + value[1], (*this).z + value[2])); } vector vector::operator- (const float (&value)[4]) const { return (vector ((*this).x - value[0], (*this).y - value[1], (*this).z - value[2])); } vector vector::operator* (const float (&value)[4]) const { return (vector ((*this).x * value[0], (*this).y * value[1], (*this).z * value[2])); } vector vector::operator/ (const float (&value)[4]) const { assert ((value[0] != 0.0f) && (value[1] != 0.0f) && (value[2] != 0.0f)); return (vector ((*this).x / value[0], (*this).y / value[1], (*this).z / value[2])); } vector vector::operator+ (float value) const { return (vector ((*this).x + value, (*this).y + value, (*this).z + value)); } vector vector::operator- (float value) const { return (vector ((*this).x - value, (*this).y - value, (*this).z - value)); } vector vector::operator* (float value) const { return (vector ((*this).x * value, (*this).y * value, (*this).z * value)); } vector vector::operator/ (float value) const { assert (value != 0.0f); return (vector ((*this).x / value, (*this).y / value, (*this).z / value)); } vector& vector::operator+= (const vector& other) { (*this).x += other.x; (*this).y += other.y; (*this).z += other.z; // (*this).w += other.w; return (*this); } vector& vector::operator-= (const vector& other) { (*this).x -= other.x; (*this).y -= other.y; (*this).z -= other.z; // (*this).w -= other.w; return (*this); } vector& vector::operator*= (const vector& other) { (*this).x *= other.x; (*this).y *= other.y; (*this).z *= other.z; // (*this).w *= other.w; return (*this); } vector& vector::operator/= (const vector& other) { assert ((other.x != 0.0f) && (other.y != 0.0f) && (other.z != 0.0f)); (*this).x /= other.x; (*this).y /= other.y; (*this).z /= other.z; // (*this).w /= other.w; return (*this); } vector& vector::operator+= (const float (&value)[4]) { (*this).x += value[0]; (*this).y += value[1]; (*this).z += value[2]; // (*this).w += value[3]; return (*this); } vector& vector::operator-= (const float (&value)[4]) { (*this).x -= value[0]; (*this).y -= value[1]; (*this).z -= value[2]; // (*this).w -= value[3]; return (*this); } vector& vector::operator*= (const float (&value)[4]) { (*this).x *= value[0]; (*this).y *= value[1]; (*this).z *= value[2]; // (*this).w *= value[2]; return (*this); } vector& vector::operator/= (const float (&value)[4]) { assert ((value[0] != 0.0f) && (value[1] != 0.0f) && (value[2] != 0.0f)); (*this).x /= value[0]; (*this).y /= value[1]; (*this).z /= value[2]; // (*this).w /= value[3]; return (*this); } vector& vector::operator+= (float value) { (*this).x += value; (*this).y += value; (*this).z += value; // (*this).w += value; return (*this); } vector& vector::operator-= (float value) { (*this).x -= value; (*this).y -= value; (*this).z -= value; // (*this).w -= value; return (*this); } vector& vector::operator*= (float value) { (*this).x *= value; (*this).y *= value; (*this).z *= value; // (*this).w *= value; return (*this); } vector& vector::operator/= (float value) { assert (value != 0.0f); (*this).x /= value; (*this).y /= value; (*this).z /= value; // (*this).w /= value; return (*this); }
Also dann legt mal los
-
achja ich hoffe ihr nehmt die globale variable mir nicht übel, ich war nur zu faul einen singleton für diese eine variable zu erstellen
p.s.: war ebenfalls zu faul zum anmelden :D:D:D
-
also das du immer *this benutzt ist absolut lächerlich.
-
der,der fragt schrieb:
vector& vector::operator*= (const vector& other) { (*this).x *= other.x; (*this).y *= other.y; (*this).z *= other.z; // (*this).w *= other.w; return (*this); }
Glaubst du, damit kriegst du den Job?
-
:-(((((( schrieb:
also das du immer *this benutzt ist absolut lächerlich.
Naja ich habs mir halt so angewöhnt, falls sowas z. B. kommt:
foo foo:set (int x, int y) { (*this).x = x; (*this).y = y; }
Früher war ich dann immer wie bescheuert am suchen wegen diesem Flüchtigkeitsfehler. Später hab ich dann bei Parametern mit selben Namen eines Attributes _ davor geschrieben, nur das (*this) ist gebielben aus Gewohntheit.
-
ich würde es so programmieren:
foo foo:set (int x, int y) { x_ = x; y_ = y; }
-
du weißt, dass es den -> operator gibt?
-
Mit Sicherheit weiß er das, aber (*this). sieht doch viel komplizierter und somit toller aus *troll*
Ich umgehe das Problem indem ich m_ benutze *weitertroll* :p
-
1.) Wenn du schon überall this benutzen willst, dann wenigstens this-> und nicht dieses eklige (*this).
2.) Wieso inline asm? zum Posen?
3.) Naja, is halt ein Vektor, wie man ihn scho 100Mal gesehen hat. Allerdings könnte ich bei deinem Vektor sowas nicht machen:v = 2.0f * v2;
-
dfgdf schrieb:
Mit Sicherheit weiß er das, aber (*this). sieht doch viel komplizierter und somit toller aus *troll*
Ich umgehe das Problem indem ich m_ benutze *weitertroll* :p
Türlich kenn ich den -> operator! Doch ich finde diese schreibweise irgendwie zutreffender. Naja egal.
Die Sache mit dem m_ habe ich mir abgewöhnt, da es sonst wieder nur FlameWars gibt!
-
war auf der,der fragt bezogen nicht auf nix da
-
op+, op* etc gehören nicht in die Klasse. Sollten freie Funktionen sein. Genauso einige andere Funktionen. Zum Beispiel angleWith... warum nicht als frei Funktion mit zwei Argumenten?
-
Wenn du schon Inline Assembler benutzt, dann kommentier auch was der macht. Das (*this) ist extrem unleserlich und daraus folgt schlecht. Privat kannst du das machen, aber wenn du dich bewerben willst, lass so ein Blödsinn weg.
Dann ist dein Code nicht const-correct und ich würde eine Menge hier inlinen.
Dann solltest du nicht alle Operatoren als Member implementieren (siehe http://www.gotw.ca/gotw/004.htm).
void würde ich an deiner Stelle nicht mehr explizit bei Parametern angeben!
Und du verletzt das OpenClosed Prinzip.
-
Jester schrieb:
op+, op* etc gehören nicht in die Klasse. Sollten freie Funktionen sein. Genauso einige andere Funktionen. Zum Beispiel angleWith... warum nicht als frei Funktion mit zwei Argumenten?
weil ich nicht umbedingt immer sowas schreiben wollte:
vector angle (0,0,0; angle = angle2 (vector1, vector2);
-
kingruedi
Danke für die Hinweise, doch da muss ich etwas "nachharken":
1. Was genau ist nicht "const-correct".
2. Womit verstoße ich (neben der Globalen Variable) das OCP?
3. Die Sache mit dem void, was hat es damit auf sich?naja das mit den Operatoren wusste ich nicht, aber man lernt nie aus
und das mit inline kommt noch
Danke für den Hinweis
-
nix da schrieb:
kingruedi
Danke für die Hinweise, doch da muss ich etwas "nachharken":
1. Was genau ist nicht "const-correct".Steht doch in dem Link.
2. Womit verstoße ich (neben der Globalen Variable) das OCP?
Die globale Var. hat damit nichts zu tun. Bei dir is alles public.
[/quote]3. Die Sache mit dem void, was hat es damit auf sich?
Es ist überflüssig und sieht IMHO hässlich aus.
-
1. Member Funktionen, die das Objekt nicht verändern solltest du als const deklarieren. Siehe auch den Link
2. Die Variablen sind in der public Schnitstelle. Auch hier solltest du den Link lesen
3. Du kannst einfach void foo() anstelle void foo(void) schreiben, dass ist IMHO leserlicher. void als Parameter ist ein überbleibsel aus alten C Zeiten, da eine leere Parameterliste AFAIK beliebige Parameter bedeutete.
-
kingruedi schrieb:
2. Die Variablen sind in der public Schnitstelle. Auch hier solltest du den Link lesen
Naja ich wollte es eigentlich konfortabel halten und nicht immer sowas machen:
float _31 = vector.getX();
Das würde bei einer 4x4 Matrix schon sehr auf die Performance hauen, sofern ich mir das Logisch zusammen wurschtel, vorallem bei Matrizenmulitplikationen. Währe es zu Sachen des "Speeds" nicht logisch das OCP zu "sträken"? Denn ich weis nicht eine get_32() funktion bei einer Matrixklasse fände ich extrem bäh.
zum void: ich finde das bei Syntaxhighlight schöner und erkennlicher, aber jedem das seine, denkst du das ist ein Starkes Kriterium?
-
kingruedi schrieb:
void als Parameter ist ein überbleibsel aus alten C Zeiten, da eine leere Parameterliste AFAIK beliebige Parameter bedeutete.
Das ist heute immer noch so. Wo da der Sinn ist, würde mich aber interessieren. Oder kommt das einem void func(...); gleich? .oO(geht das eigentlich? hab ich noch nie gesehen...)
-
@Nix da:
währe?? sträken?? weis ??
Du nix Deutsch