Beispiel für das Überladen von Operatoren
Nach oben zu Überladen von Operatorfunktionen (Übersicht) - Index
Das folgende Beispiel erweitert die Klasse complex, um einen Vektor vom Typ complex zu erzeugen. Einige der nützlichsten Operatoren sind überladen, um die üblichen mathematischen Operationen in der gewohnten mathematischen Syntax zu ermöglichen.
Einige der Themen sind im folgenden Beispiel dargestellt:
- Der Standardkonstruktor ist definiert. Das wird nur vom Compiler unterstützt, wenn Sie weder einen Standardkonstruktor noch einen anderen definiert haben.
- Der Kopierkonstruktor ist explizit definiert. Normalerweise, wenn Sie keine Konstruktoren definiert haben, stellt Ihnen der Compiler einen zur Verfügung. Sie sollten den Kopierkonstuktor definieren, wenn Sie den Zuweisungsoperator überladen.
- Der Zuweisungsoperator ist überladen. Wenn Sie den Zuweisungsoperator nicht überladen, ruft der Compiler den Standard-Zuweisungsoperator auf, wenn er benötigt wird. Durch das Überladen der Zuweisung vom Typ cvector legen Sie die auszuführenden Aktivitäten exakt fest. Beachten Sie, dass abgeleitete Klassen keinen Zuweisungsoperator erben können.
- Der Indexoperator ist als Elementfunktion (wird beim Überladen benötigt) mit einem einzigen Element definiert. Die Version vom Typ const stellt für den Aufrufer sicher, dass das Argument nicht verändert wird. Das ist beim beim Kopieren und Zuweisen nützlich. Der Operator sollt prüfen, dass sich der Indexwert innerhalb des gültigen Bereiches befindet. Hier ergibt sich eine gute Anwendungsmöglichkeit für die Exception-Behandlung.
- Der Additionsoperator ist als eine Elementfunktion definiert. Er erlaubt das Addieren nur für die Typen cvector. Die Addition sollte immer überprüfen, ob die Größen der Operanden zueinander kompatibel sind.
- Der Multiplikations-Operator wird als friend deklariert. Dadurch lässt sich die Reihenfolge der Operanden definieren. Ein Versuch, die Anordnung der Operanden umzukehren, führt während des Compilierens zu einem Fehler.
- Der Operator zu Einfügen von Streams ist überladen, um cvector auf eine natürliche Weise anzuzeigen. Große Objekte, die nicht gut auf einem Bildschirm mit begrenzter Größe angezeigt werden, könnten eine andere Strategie zum Anzeigen benötigen.
Quellbeispiel
/* Wie man die Klasse complex erweitert und die benötigten Operatoren überlädt. */
complexcomplexcomplex
#include <complex> // Damit ist iostream einbezogen
using namespace std;
// Komplexe Vektoren
template <class T>
class cvector {
int size;
complex<T> *data;
public:
cvector() { size = 0; data = NULL; };
cvector(int i = 5) : size(i) { // Standardvektorgröße.
data = new complex<T>[size];
for (int j = 0; j < size; j++)
data[j] = j + (0.1 * j); // Willkürliche Initialisierung.
};
/* DIESE VERSION WIRD IN main() AUFGERUFEN */
complex<T>& operator [](int i) { return data[i]; };
/* DIESE VERSION WIRD UM ZUWEISUNGSOPERATOR AUFGERUFEN UND KOPIERT DEN KONSTRUKTOR */
const complex<T>& operator [](int i) const { return data[i]; };
cvector operator +(cvector& A) { // ADDITIONSOPERATOR
cvector result(A.size); // Original nicht verändern
for (int i = 0; i < size; i++)
result[i] = data[i] + A.data[i];
return result;
};
/* WEIL DIE MULTIPLIKATION * vector MULTIPLICATION NICHT KOMMUNIKATIV IST, MUSS DIE ANORDNUNG DER ELEMENTE FESTGELEGT WERDEN.
DIE ELEMENTE MÜSSEN ANGEGEBEN SEIN. DIESE FRIEND-OPERATORFUNKTION
STELLT DIE RICHTIGE MULTIPLIKATION SICHER. */
friend cvector operator *(T scalar, cvector& A) {
cvector result(A.size); // Original nicht verändern
for (int i = 0; i < A.size; i++)
result.data[i] = scalar * A.data[i];
return result;
}
/* DER OPERATOR ZUM EINFÜGEN VON STREAMS. */
friend ostream& operator <<(ostream& out_data, cvector& C) {
for (int i = 0; i < C.size; i++)
out_data << "[" << i << "]=" << C.data[i] << " ";
cout << endl;
return out_data;
};
cvector( const cvector &C ) { // KOPIERKONSTRUCTOR
size = C.size;
data = new complex<T>[size];
for (int i = 0; i < size; i++)
data[i] = C[i];
}
cvector& operator =(const cvector &C) { // ZUWEISUNGSOPERATOR.
if (this == &C) return *this;
delete[] data;
size = C.size;
data = new complex<T>[size];
for (int i = 0; i < size; i++)
data[i] = C[i];
return *this;
};
virtual ~cvector() { delete[] data; }; // DESTRUKTOR
};
int main(void) { /* EIN PAAR OPERATIONEN MIT complex VEKTOREN. */
cvector<float> cvector1(4), cvector2(4), result(4);
// ERZEUGT ZAHLEN VOM TYP complex UND WEIST SIE AN VEKTOREN VOM TYP complex ZU.
cvector1[3] = complex<float>(3.3, 102.8);
cout <<"Hier ist cvector1:" << endl;
cout << cvector1;
cvector2[3] = complex<float>(33.3, 81);
cout << "Hier ist cvector2:" << endl;
cout << cvector2;
result = cvector1 + cvector2;
cout << "Das Ergebnis der Vektoraddition:" << endl;
cout << result;
result = 10 * cvector2;
cout << "Das Ergebnis von 10 * cvector2:" << endl;
cout << result;
return 0;
}
Ausgabe
Hier ist cvector1:
[0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(3.3, 102.8)
Hier ist cvector2:
[0]=(0, 0) [1]=(1.1, 0) [2]=(2.2, 0) [3]=(33.3, 81)
Das Ergebnis der Vektoraddition:
[0]=(0, 0) [1]=(2.2, 0) [2]=(4.4, 0) [3]=(36.6, 183.8)
Das Ergebnis von 10 * cvector2:
[0]=(0, 0) [1]=(11, 0) [2]=(22, 0) [3]=(333, 810)