1、operator
operator是C++关键字之一, 称为重载运算符(也称“重载操作符”)。所谓重载,就是赋予新的含义。函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作。运算符重载(Operator Overloading)也是一个道理,同一个运算符可以有不同的功能。
例如,+号可以对不同类型(int、float 等)的数据进行加法操作;<<既是位移运算符,又可以配合cout向控制台输出数据。C++本身已经对这些运算符进行了重载。C++也允许程序员自己重载运算符,这给我们带来了很大的便利。
实现运算符重载的方式通常有以下两种:
(1)运算符重载实现为类的成员函数;
(2)运算符重载实现为非类的成员函数(即全局函数)。
2、重载为类的成员函数(以“==”举例)
在类体中声明(定义)需要重载的运算符,声明方式跟普通的成员函数一样,只不过运算符重载函数的名字是【operator紧跟一个C++预定义的操作符】【以“==”为例,函数名就是“operator==”】。
(1)在类中实现函数的逻辑:
#include <iostream>
using namespace std;
class student
{
private:
char name[10];
int age;
public:
student(int nAge) // 构造函数,对私有变量赋值
{
this->age = nAge;
}
bool operator==(const student& ps) // 重载了“==”运算符,用于判断两个值是否相等
{
if (this->age == ps.age)
return true;
return false;
}
};
int main()
{
student p1(10);
student p2(10);
if (p1 == p2)
cout << "p1 is equal with p2." << endl;
else
cout << "p1 is not equal with p2." << endl;
return 0;
}
输出:
p1 is equal with p2.
(2)在类外实现函数的逻辑:
#include <iostream>
using namespace std;
class student
{
private:
char name[10];
int age;
public:
student(int nAge) // 构造函数,对私有变量赋值
{
this->age = nAge;
}
bool operator==(const student& ps); // 重载了“==”运算符,用于判断两个值是否相等
};
bool student::operator==(const student& ps)
{
if (this->age == ps.age)
return true;
return false;
}
int main()
{
student p1(10);
student p2(10);
if (p1 == p2)
cout << "p1 is equal with p2." << endl;
else
cout << "p1 is not equal with p2." << endl;
return 0;
}
输出:
p1 is equal with p2.
3、重载为全局函数(以“==”举例)
对于全局重载运算符,代表左操作数的参数必须被显式指定。
#include <iostream>
using namespace std;
class student
{
public:
char name[10];
int age;
};
// 左操作数的类型必须被显式指定;此处指定的类型为person类
bool operator==(student const& p1, student const& p2)
{
if (p1.age == p2.age)
return true;
else
return false;
}
int main()
{
student p1;
student p2;
p1.age = 18;
p2.age = 18;
if (p1 == p2)
cout << "p1 is equal with p2." << endl;
else
cout << "p1 is NOT equal with p2." << endl;
return 0;
}
输出:
p1 is equal with p2.
4、重载“数学运算符”
四则运算符(+、-、*、/、+=、-=、*=、/=)和关系运算符(>、<、<=、>=、==、!=)都是数学运算符,它们在实际开发中非常常见,被重载的几率也很高,并且有着相似的重载格式。本文以复数类 Complex 为例对它们进行重载,重在演示运算符重载的语法以及规范。
复数能够进行完整的四则运算,但不能进行完整的关系运算:我们只能判断两个复数是否相等,但不能比较它们的大小,所以不能对 >、<、<=、>= 进行重载
#include <iostream>
#include <cmath>
using namespace std;
//复数类
class Complex {
public:
//构造函数
Complex(double real = 0.0, double imag = 0.0) : m_real(real), m_imag(imag) { }
public:
//运算符重载
//以全局函数的形式重载
friend Complex operator+(const Complex& c1, const Complex& c2);
friend Complex operator-(const Complex& c1, const Complex& c2);
friend Complex operator*(const Complex& c1, const Complex& c2);
friend Complex operator/(const Complex& c1, const Complex& c2);
friend bool operator==(const Complex& c1, const Complex& c2);
friend bool operator!=(const Complex& c1, const Complex& c2);
//以成员函数的形式重载
Complex& operator+=(const Complex& c);
Complex& operator-=(const Complex& c);
Complex& operator*=(const Complex& c);
Complex& operator/=(const Complex& c);
public:
//成员函数
double real() const { return m_real; }
double imag() const { return m_imag; }
private:
double m_real; //实部
double m_imag; //虚部
};
//重载为全局函数
//重载+运算符
Complex operator+(const Complex& c1, const Complex& c2) {
Complex c;
c.m_real = c1.m_real + c2.m_real;
c.m_imag = c1.m_imag + c2.m_imag;
return c;
}
//重载-运算符
Complex operator-(const Complex& c1, const Complex& c2) {
Complex c;
c.m_real = c1.m_real - c2.m_real;
c.m_imag = c1.m_imag - c2.m_imag;
return c;
}
//重载*运算符 (a+bi) * (c+di) = (ac-bd) + (bc+ad)i
Complex operator*(const Complex& c1, const Complex& c2) {
Complex c;
c.m_real = c1.m_real * c2.m_real - c1.m_imag * c2.m_imag;
c.m_imag = c1.m_imag * c2.m_real + c1.m_real * c2.m_imag;
return c;
}
//重载/运算符 (a+bi) / (c+di) = [(ac+bd) / (c²+d²)] + [(bc-ad) / (c²+d²)]i
Complex operator/(const Complex& c1, const Complex& c2) {
Complex c;
c.m_real = (c1.m_real * c2.m_real + c1.m_imag * c2.m_imag) / (pow(c2.m_real, 2) + pow(c2.m_imag, 2));
c.m_imag = (c1.m_imag * c2.m_real - c1.m_real * c2.m_imag) / (pow(c2.m_real, 2) + pow(c2.m_imag, 2));
return c;
}
//重载==运算符
bool operator==(const Complex& c1, const Complex& c2) {
if (c1.m_real == c2.m_real && c1.m_imag == c2.m_imag) {
return true;
}
else {
return false;
}
}
//重载!=运算符
bool operator!=(const Complex& c1, const Complex& c2) {
if (c1.m_real != c2.m_real || c1.m_imag != c2.m_imag) {
return true;
}
else {
return false;
}
}
//重载为成员函数
//重载+=运算符
Complex& Complex::operator+=(const Complex& c) {
this->m_real += c.m_real;
this->m_imag += c.m_imag;
return *this;
}
//重载-=运算符
Complex& Complex::operator-=(const Complex& c) {
this->m_real -= c.m_real;
this->m_imag -= c.m_imag;
return *this;
}
//重载*=运算符
Complex& Complex::operator*=(const Complex& c) {
this->m_real = this->m_real * c.m_real - this->m_imag * c.m_imag;
this->m_imag = this->m_imag * c.m_real + this->m_real * c.m_imag;
return *this;
}
//重载/=运算符
Complex& Complex::operator/=(const Complex& c) {
this->m_real = (this->m_real * c.m_real + this->m_imag * c.m_imag) / (pow(c.m_real, 2) + pow(c.m_imag, 2));
this->m_imag = (this->m_imag * c.m_real - this->m_real * c.m_imag) / (pow(c.m_real, 2) + pow(c.m_imag, 2));
return *this;
}
int main() {
Complex c1(25, 35);
Complex c2(10, 20);
Complex c3(1, 2);
Complex c4(4, 9);
Complex c5(34, 6);
Complex c6(80, 90);
Complex c7 = c1 + c2;
Complex c8 = c1 - c2;
Complex c9 = c1 * c2;
Complex c10 = c1 / c2;
cout << "c7 = " << c7.real() << " + " << c7.imag() << "i" << endl;
cout << "c8 = " << c8.real() << " + " << c8.imag() << "i" << endl;
cout << "c9 = " << c9.real() << " + " << c9.imag() << "i" << endl;
cout << "c10 = " << c10.real() << " + " << c10.imag() << "i" << endl;
c3 += c1;
c4 -= c2;
c5 *= c2;
c6 /= c2;
cout << "c3 = " << c3.real() << " + " << c3.imag() << "i" << endl;
cout << "c4 = " << c4.real() << " + " << c4.imag() << "i" << endl;
cout << "c5 = " << c5.real() << " + " << c5.imag() << "i" << endl;
cout << "c6 = " << c6.real() << " + " << c6.imag() << "i" << endl;
if (c1 == c2) {
cout << "c1 == c2" << endl;
}
if (c1 != c2) {
cout << "c1 != c2" << endl;
}
return 0;
}
输出:
c7 = 35 + 55i
c8 = 15 + 15i
c9 = -450 + 850i
c10 = 1.9 + -0.3i
c3 = 26 + 37i
c4 = -6 + -11i
c5 = 220 + 4460i
c6 = 5.2 + 1.592i
c1 != c2
5、重载“>>”和“<<”
在C++中,标准库本身已经对左移运算符“<<”和右移运算符“>>”分别进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是C++内置的数据类型(例如 bool、int、double 等)和标准库所包含的类类型(例如 string、complex、ofstream、ifstream 等)。
如果我们自己定义了一种新的数据类型,需要用输入输出运算符去处理,那么就必须对它们进行重载。本节以前面的complex类为例来演示输入输出运算符的重载。
本节要达到的目标是让复数的输入输出和int、float等基本类型一样简单。假设num1、num2是复数,那么输出形式就是:
cout<<num1<<num2<<endl;
输入形式就是:
cin>>num1>>num2;
cout是ostream类的对象,cin是istream类的对象,要想达到这个目标,就必须以全局函数(友元函数)的形式重载“<<”和“>>”。
#include <iostream>
using namespace std;
class complex {
public:
complex(double real = 0.0, double imag = 0.0) : m_real(real), m_imag(imag) { };
public:
friend complex operator+(const complex& A, const complex& B);
friend complex operator-(const complex& A, const complex& B);
friend complex operator*(const complex& A, const complex& B);
friend complex operator/(const complex& A, const complex& B);
//重载输入输出运算符
friend istream& operator>>(istream& in, complex& A);
friend ostream& operator<<(ostream& out, complex& A);
private:
double m_real; //实部
double m_imag; //虚部
};
//重载加法运算符
complex operator+(const complex& A, const complex& B) {
complex C;
C.m_real = A.m_real + B.m_real;
C.m_imag = A.m_imag + B.m_imag;
return C;
}
//重载减法运算符
complex operator-(const complex& A, const complex& B) {
complex C;
C.m_real = A.m_real - B.m_real;
C.m_imag = A.m_imag - B.m_imag;
return C;
}
//重载乘法运算符
complex operator*(const complex& A, const complex& B) {
complex C;
C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
return C;
}
//重载除法运算符
complex operator/(const complex& A, const complex& B) {
complex C;
double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag) / square;
C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag) / square;
return C;
}
//重载输入运算符
istream& operator>>(istream& in, complex& A) {
in >> A.m_real >> A.m_imag;
return in;
}
//重载输出运算符
ostream& operator<<(ostream& out, complex& A) {
out << A.m_real << " + " << A.m_imag << " i ";;
return out;
}
int main() {
complex c1, c2, c3;
cin >> c1 >> c2;
c3 = c1 + c2;
cout << "c1 + c2 = " << c3 << endl;
c3 = c1 - c2;
cout << "c1 - c2 = " << c3 << endl;
c3 = c1 * c2;
cout << "c1 * c2 = " << c3 << endl;
c3 = c1 / c2;
cout << "c1 / c2 = " << c3 << endl;
return 0;
}
输出:
1.2 3.4
56.4 7.8
c1 + c2 = 57.6 + 11.2 i
c1 - c2 = -55.2 + -4.4 i
c1 * c2 = 41.16 + 201.12 i
c1 / c2 = 7.24615 + 14.0308 i
6、其他重载
7、参考
参考案例过多,暂不进行列举。