運算符重載的宏觀思考The Complex Class
運算符重載是C++中較C語言更加先進和靈活的地方之一,通過運算符重載,使運算符擁有了除了只能完成內置類型的運算操作之外的對於其他自定義類型的運算功能。這使得C++更加靈活,通俗,更加面向對象。
事實上運算符的重載不過是對函數名為“operator 運算符”的函數的定義,根據所操作的對象的不同,可以分為成員函數和友元函數兩種定義方法。
C++中唯一的三目運算符不能重載,因此所有的運算符重載的形參都不會超過三個,又由於成員函數默認第一個形參必須是自定義類的對象並且默認綁定到*this指針,所以所有的重載為成員函數的運算符重載的形參都不會超過一個。如此說來,左操作數不是自定義的類型的對象是不能和自定義程序的對象運算了?所以我們引進了友元函數,當左操作數不是自定義類型時,可以定義友元函數,由兩個形參,左形參是自由類型,右形參是自定義類型,返回自定義類型。這樣就可以實現同一類型,不同類型之間的相互運算,並且不受對稱性的幹擾。算術用算符不存在對稱性,有需要時要一一重載。
友元函數和成員函數並無差別,不過是多了聲明和一個左類型對象這些形式上的東西,所以重載為友元函數或成員函數是靈活機動的。但有兩個運算符的重載必須重載為友元函數,即輸入輸出運算符,這是兩個包含在標準庫istream和ostream中的兩個運算符,不僅要重載為友元函數,而且返回值類型必須是istream或ostream,不能反回自定義類型因為二義性引起編譯錯誤。其他除了必須重載為成員函數的賦值運算符(=)下標運算符([])調用運算符(())成員訪問運算符(->)以及絕大多數重載為成員函數的復合求值運算符還有改變對象狀態的自增自減運算符和解引用運算符,其他運算符的重載是非常自由的。
以The Complex Class為例
#include <iostream> #include <stdio.h> using namespace std; class Complex { double re; //real part of a complex number double im; //imaginary part of a complex number public: Complex() { re = 0; im = 0; } Complex(double a,doubleb = 0) { re = a; im = b; } Complex(const Complex& B) { re = B.re; im = B.im; } double real() const { return re; } double imag() const { return im; } friend ostream &operator<<(ostream &os,const Complex &c) { //輸出運算符重載為友元函數,返回ostream類型 os << "(" << c.re << "," << c.im << ")"; return os; } friend istream &operator>>(istream &is,Complex &c) { //輸入運算符重載為友元函數,右形參不加const,返回istream char i; is >> i >> c.re >> i >> c.im >> i; //在輸入運算符重載中輸入變量 return is; } Complex operator+(const Complex& B) { //一般重載,重載為成員函數,右形參為complex Complex temp; temp.re = re + B.re; temp.im = im + B.im; return temp; } Complex& operator+=(const Complex& B) { re += B.re; im += B.im; return *this; } Complex operator+(double num) { //一般重載,重載為成員函數,右形參為double Complex temp; temp.re = re + num; temp.im = im; return temp; } friend Complex operator+(double num,const Complex & B) { //重載為友元,左形參為double,返回complex Complex temp; temp.re = B.re + num; temp.im = B.im; return temp; } Complex operator-(const Complex& B) { Complex temp; temp.re = re - B.re; temp.im = im - B.im; return temp; } Complex operator-(double num) { Complex temp; temp.re = re - num; temp.im = im; return temp; } friend Complex operator-(double num,const Complex & B) { Complex temp; temp.re = num - B.re; temp.im = -B.im; return temp; } Complex& operator-=(const Complex& B) { //復合求值運算符,一般重載為成員函數, re -= B.re; im -= B.im; return *this; } Complex operator*(const Complex& B) { Complex temp; temp.re = re * B.re - im * B.im; temp.im = im * B.re + re * B.im; return temp; } Complex operator*(double num) { Complex temp; temp.re = re * num; temp.im = im * num; return temp; } friend Complex operator*(double num,const Complex & B) { Complex temp; temp.re = num * B.re; temp.im = B.im * num; return temp; } Complex& operator*=(const Complex& B) { double temp1 = re, temp2 = im; re = temp1 * B.real() - temp2 * B.imag(); im = temp1 * B.imag() + temp2 * B.real(); return *this; } Complex operator/(const Complex& B) { Complex temp; temp.re = (re * B.re + im * B.im) / (B.re * B.re + B.im * B.im); temp.im = (im * B.re - re * B.im) / (B.re * B.re + B.im * B.im); return temp; } Complex& operator/=(const Complex& B) { Complex temp; temp.re = (re * B.re + im * B.im) / (B.re * B.re + B.im * B.im); temp.im = (im * B.re - re * B.im) / (B.re * B.re + B.im * B.im); re = temp.re; im = temp.im; return *this; } Complex operator/(double num) { Complex temp; temp.re = re / num; temp.im = im / num; return temp; } friend Complex operator/(double num,const Complex & B) { Complex temp; temp.re = (num * B.re) / (B.re * B.re + B.im * B.im); temp.im = ((-num) * B.im) / (B.re * B.re + B.im * B.im); return temp; } bool operator == (const Complex& B) { //關系運算符重載為成員函數,右形參為complex類型 if (re - B.re < 1e-10 && im - B.im < 1e-10) { return true; } else { return false; } } bool operator != (const Complex& B) { if (re - B.re < 1e-10 && im - B.im < 1e-10) { return false; } else { return true; } } bool operator == (double num) { //關系運算符重載為成員函數,右形參為double類型 if (re - num < 1e-10 && im - 0.0 < 1e-10) { return true; } else { return false; } } bool operator != (double num) { if (re - num < 1e-10 && im - 0.0 < 1e-10) { return false; } else { return true; } } friend bool operator == (double num, const Complex& B) { //關系運算符重載成友元函數,左形參為double類型 if (B.re - num < 1e-10 && B.im - 0.0 < 1e-10) { return true; } else { return false; } } friend bool operator != (double num, const Complex& B) { if (B.re == num && B.im == 0) { return false; } else { return true; } } Complex operator-() { //取反運算符,改變對象裝態,重載為友元函數 Complex temp; temp.re = -re; temp.im = -im; return temp; } };
用來調試的主程序:
#include<iostream> #include<string> #include"source.h" using namespace std; void f() { Complex a; cout << a << endl; Complex b = Complex(1,1.5); cout << b << endl; Complex c(3.5); cout << c << endl; c += a; cout << c << endl; c = c + a; cout << c << endl; c = c + 2.5; cout << c << endl; c = 2.5 + c; cout << c << endl; c -= a; cout << c << endl; c = c - a; cout << c << endl; c = c - 2.5; cout << c << endl; c = 2.5 - b; cout << c << endl; c *= b; cout << c << endl; c = c * b; //cout << c << endl; c = c * 2.5; //cout << c << endl; c = 2.5 * c; //cout << c << endl; c /= b; //cout << c << endl; c = c / b; //cout << c << endl; c = c / 2.5; //cout << c << endl; c = 2.5 / c; //cout << c << endl; c = -b; cout << c << endl; cout << (a==a) << endl; //output 1 cout << (a==0.0) << endl; //output 1 cout << (0.0==a) << endl; //output 1 cout << (a!=a) << endl; //output 0 cout << (a!=0.0) << endl; //output 0 cout << (0.0!=a) << endl; //output 0 //cout << a+2.5 << endl; //cout << 2.5+a << endl; //cout << a+b << endl; //c = a+2.5+a + b*2.5*b; while (cin >> c) { cout << c << endl; //cout << "(" << c.real() << "," << c.imag() << ")" << endl; } } int main() { f(); return 0; }
運算符重載的宏觀思考The Complex Class