Template Vector Klasse gemacht (kein problem nur mal zeigen willsch)
-
Normalerweise haben die Operatoren +=, -=, ... den Vorteil keine überflüssigen Temporären Objekte zu erzeugen. Deine Variante verwendet aber intern +, -, ... und erzeugt somit viel overhead, der nicht nötig ist.
template<class T> inline const CVector<T>& CVector<T>::operator+=(const CVector& a) { m_x += a.m_x; m_y += a.m_y; m_z += a.m_z; return *this; } // den würde ich zwar eh nicht als Methode machen, aber egal template<class T> inline const CVector<T> CVector<T>::operator+(const CVector& a) { CVector<T> temp(*this); return temp += a; }
Und dann das:
template<class T> inline CVector<T> CVector<T>::Normalize() const { T fMag = Magnitude(); CVector<T> vec(*this); vec /= Magnitude(); return vec; }
Muss man das verstehen? wofür wird fMag angelegt? was bedeutet das Präfix f?
Und bei "Normalize" erwarte ich, dass der Vektor selbst normalisiert wird, nicht dass ich eine normalisierte Kopie erhalte. Denk mal über den Namen nach./edit siehe Jesters post (kommt vom copy und paste)
-
#ifndef CVECTOR_ #define CVECTOR_ #include <d3d9.h> // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> class CVector { protected: T m_x, m_y, m_z; public: CVector(T x = T(), T y = T(), T z = T()) : m_x(x), m_y(y), m_z(z) {} T getX() const {return m_x;} T getY() const {return m_y;} T getZ() const {return m_z;} void setX(T t) {m_x = t;} void setY(T t) {m_y = t;} void setZ(T t) {m_z = t;} void setVector(T x, T y, T z); D3DVECTOR getD3DVECTOR(); const CVector<T> operator-(const CVector<T>&) const; const CVector<T> operator+(const CVector<T>&) const; T operator*(const CVector<T>&) const; CVector<T> operator*(T val) const; CVector<T> operator/(T val) const; CVector<T> operator/(const CVector<T>&) const; CVector<T>& operator=(const CVector<T>&); CVector<T> operator-(); CVector<T>& operator+=(const CVector<T>&); CVector<T>& operator-=(const CVector<T>&); CVector<T>& operator*=(const CVector<T>&); CVector<T>& operator*=(T); CVector<T>& operator/=(const CVector<T>&); CVector<T>& operator/=(T); CVector<T> CrossProduct(const CVector<T>&) const; CVector<T> Normalize(); T Magnitude() const; T MagnitudeQuad() const; virtual ~CVector<T>() {}; }; // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline const CVector<T> CVector<T>::operator-(const CVector<T>& a) const { CVector<T> vec(*this); return vec -= a; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline const CVector<T> CVector<T>::operator+(const CVector<T>& a) const { return CVector(m_x + a.m_x, m_y + a.m_y, m_z + a.m_z); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> T CVector<T>::operator*(const CVector& a) const { return m_x * a.m_x + m_y * a.m_y + m_z * a.m_z; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T> CVector<T>::CrossProduct(const CVector& a) const { return CVector(m_y * a.m_z - m_z * a.m_y, m_z * a.m_x - m_x * a.m_z, m_x * a.m_y - m_y * a.m_x); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> T CVector<T>::Magnitude() const { return static_cast<T>(sqrt(m_x * m_x + m_y * m_y + m_z * m_z)); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> T CVector<T>::MagnitudeQuad() const { return static_cast<T>(m_x * m_x + m_y * m_y + m_z * m_z); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator/=(const CVector& a) { m_x /= a.m_x; m_y /= a.m_y; m_z /= a.m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T> CVector<T>::Normalize() { return (*this) /= Magnitude(); } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> CVector<T>& CVector<T>::operator=(const CVector& a) { m_x = a.m_x; m_y = a.m_y; m_z = a.m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator+=(const CVector& a) { m_x += a.m_x; m_y += a.m_y; m_z += a.m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator-=(const CVector& a) { m_x -= a.m_x; m_y -= a.m_y; m_z -= a.m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T> CVector<T>::operator*(T val) const { CVector<T> vec(*this); return vec *= val; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T> CVector<T>::operator/(T val) const { CVector<T> vec(*this); return vec /= val; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator*=(const CVector& a) { m_x *= a.m_x; m_y *= a.m_y; m_z *= a.m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator*=(T val) { m_x *= val; m_y *= val; m_z *= val; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> inline CVector<T>& CVector<T>::operator/=(T val) { m_x /= val; m_y /= val; m_z /= val; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> void CVector<T>::setVector(T x, T y, T z) { m_x = m_x; m_y = m_y; m_z = m_z; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> CVector<T> CVector<T>::operator-() { m_x = -m_x; m_y = -m_y; m_z = -m_z; return *this; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ template<class T> D3DVECTOR CVector<T>::getD3DVECTOR() { D3DVECTOR v; v.x = m_x; v.y = m_y; v.z = m_z; return v; } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #endif
-
Dein operator+ gibt eine Referenz auf ein lokales Objekt zurück.
-
Mis2com schrieb:
template<class T> void CVector<T>::setVector(T x, T y, T z) { m_x = m_x; m_y = m_y; m_z = m_z; }
Äh, jetzt schau dir mal das genau an... das kann doch nicht absicht sein?!?
-junix
-
...
Du hast natürlich Recht.
Danke!
-
Ich würde die Member-Variablen weder public noch protected machen, sondern private.
Wenn Du sie protected machst, hast Du im Endeffekt das gleiche Problem, wie wenn sie public sind: Du verlierst die Kontrolle darüber, weil Du ja nicht weißt, was Programmierer X in Ableitung Y damit macht.
Protected sollte man imho nur für Methoden verwenden, aber niemals nicht für Attribute.
-
I.d.F. wahrscheinlich besser, aber überleg doch mal, wenn du was mit Vererbung machst, müssen auch die Tochterklassen auf die Elemente zugreifen können, also protected.
-
Basisklassen können get* und set* benutzen (und wenn es die nicht gibt, definiert man sie halt nur protected). (Ob man das in der Praxis durchhält, ist eine andere Sache, aber bisher lebe ich ganz gut damit...) Und von CVector abzuleiten macht imho eh nie viel Sinn, ich würde die Klasse als Nicht-Basisklasse definieren (ohne virtuellen Destruktor und ohne protected - ein final-keyword gibts ja nicht).
-
Jojo, ist jetzt auch niht mehr als Basisklasse verfügbar, weil der V table mehr Speicher belegt hat, als ok war.
Denn ich nehme das auch bei Low Poly Sachen und da muss das genau 12 Byte haben.
-
Jojo, ist jetzt auch niht mehr als Basisklasse verfügbar, weil der V table mehr Speicher belegt hat, als ok war
Die Größe der vtable hat keinen Einfluss auf die Größe der Vektor-Instanzen. Was du meinst ist der vptr, also der in jeder Instanz einer polymorphen Klasse enthaltene Zeiger auf die vtable der entsprechenden Klasse (die gibt es also nur genau einmal).
Aber nicht vergessen: vtable und vptr sind zwar gängige Implementationstechniken. Der Standard schreibt sowas aber nicht vor.Das ändert natürlich alles nichts an der Tatsache, dass ein virtueller Dtor in deinem Fall blödsinnig ist.
-
cd9000 schrieb:
btw:
#ifndef _CVECTOR_ #define _CVECTOR_ // ... #endif
Das ist nicht erlaubt. Defines dürfen nicht mit einem Unterstrich beginnen, außer sie sind vom Compiler oder einem compilereigenen Header selbst definiert worden.
Und ich hab mirs extra angewoehnt, da die ATL(von M$) alle Include Guards nach folgendem Muster generiert __INCLUDEFILENAMEOHNEDOTH_H_
mir die Kugel geb !
ciao ...
-
Achso der vptr...
Gut zu wissen