Simple Vektorklasse (Übungsaufgabe in der Bibel)
-
Guten Abend allerseits!
Ich habe eben eine Lösung zu Aufgabe §11.14.15 von Stroustrup's Buch (wie schon dem Titel zu entnehmen
)
geschrieben, dessen Angabe wie folgt lautet:Definieren Sie einen Typ Vec4 als Vektor von vier floats. Definieren Sie
operator[] für Vec4. Definieren Sie die Operatoren +, -, *, /, =, +=, -=, */
und /= für Kombinationen aus Vec4 und float.Ok, eigentlich nichts besonderes, aber ich würde gerne wissen, was ihr von
meiner Klasse haltet und vielleicht anders machen würdet (ist sicher einiges).
Hier die Schnittstelle:
#ifndef VEC_INCLUDED #define VEC_INCLUDED class Vec4 { public: Vec4(float = 1.0f); Vec4(float, float, float, float); // Zugriff auf die Elemente (keine Bereichsueberpruefung!) const float& operator[](int index) const; float& operator[](int index) { return elements[index]; } // Manipulierende Rechenoperationen Vec4& operator+=(const Vec4&); Vec4& operator-=(const Vec4&); Vec4& operator*=(const Vec4&); Vec4& operator/=(const Vec4&); // (keine Pruefung auf Division durch 0!) // Vergleichsoperator friend bool operator==(const Vec4&, const Vec4&); private: float elements[4]; }; // Rechenoperationen Vec4 operator+(const Vec4&, const Vec4&); Vec4 operator-(const Vec4&, const Vec4&); Vec4 operator*(const Vec4&, const Vec4&); Vec4 operator/(const Vec4&, const Vec4&); inline bool operator!=(const Vec4& v1, const Vec4& v2) { return !operator==(v1, v2); } #endif
Obwohl die Vergleichsoperatoren nicht gefragt waren, habe ich mal versucht
sie zu definieren.So, hier also die Implementierung der Klasse:
#include "vec.h" Vec4::Vec4(float f) { for (int i=0; i<4; i++) elements[i] = f; } Vec4::Vec4(float f1, float f2, float f3, float f4) { elements[0] = f1; elements[1] = f2; elements[2] = f3; elements[3] = f4; } Vec4& Vec4::operator+=(const Vec4& v) { for (int i=0; i<4; i++) elements[i] += v.elements[i]; return *this; } Vec4& Vec4::operator-=(const Vec4& v) { for (int i=0; i<4; i++) elements[i] -= v.elements[i]; return *this; } Vec4& Vec4::operator*=(const Vec4& v) { for (int i=0; i<4; i++) elements[i] *= v.elements[i]; return *this; } Vec4& Vec4::operator/=(const Vec4& v) { for (int i=0; i<4; i++) elements[i] /= v.elements[i]; return *this; } bool operator==(const Vec4& v1, const Vec4& v2) { for (int i=0; i<4; i++) if (v1.elements[i] != v2.elements[i]) return false; return true; } Vec4 operator+(const Vec4& v1, const Vec4& v2) { Vec4 amount = v1; return amount += v2; } Vec4 operator-(const Vec4& v1, const Vec4& v2) { Vec4 difference = v1; return difference -= v2; } Vec4 operator*(const Vec4& v1, const Vec4& v2) { Vec4 product = v1; return product *= v2; } Vec4 operator/(const Vec4& v1, const Vec4& v2) { Vec4 quotient = v1; return quotient /= v2; }
Während ich das so abschrieb fiel mir auf, dass es vielleicht besser gewesen
wäre, jeden Rechenoperator nochmal eigens für float zu überladen, anstatt
immer einen neuen Vektor konstruieren zu lassen...
Beim operator[] habe ich aus Effizienzgründen beim Index keine Bereichs-
überprüfung gemacht. Würde es eigentlich etwas bringen die beiden Konstruktoren
zu inlinen?Zuweisungsoperator und Copykonstruktor habe ich nicht definiert, da der
Default richtig sein sollte.Tja, bin mal gespannt auf eure Antworten
// EDIT:
Was mir eben noch eingefallen ist:
Es macht doch hier bereits Sinn, den Vektor jeweils per Referenz zu übergeben, oder wäre doch per Value geeigneter?gruß,
walker
-
Nö, ich denke per Referenz ist schon okay.
Du solltest vielleicht noch auf Division durch 0 achten und im Falle des Falles ne Exception werfen. Sonst schmiert das Programm einfach so ab.Außerdem machen manche der Operationen finde ich keinen Sinn:
*,/ von zwei Vektoren ist irgendwie quatsch. Zumindest in dieser Form macht es nicht allzuviel Sinn. Ich würde eher Skalar oder Kreuzprodukt erwarten.
Außerdem erscheint es etwas merkwürdig die Zahl 5 auf einen Vektor addieren zu können, bzw. davon abzuziehen.
Kurz gesagt: Ich halte die implizite Konvertierung von float zu Vektor für ein Problem. Entweder explicit machen oder ganz drauf verzichten wären meine Vorschläge. Dafür müßtest Du die passenden Operatoren natürlich dann extra zur Verfügung stellen.MfG Jester
-
Vielen Dank für die Antwort!
Ok, ich werde diesen Konstruktor mit einem Argument, der die implizite Konvertierung ermöglicht,
einfach entfernen und die Rechenoperatoren noch für float überladengruß,
walker