运算符重载
类对象不能直接参与运算,需要对运算符进行重载。
运算符预定义的操作只能针对基本数据类型,但是对于自定义类型,若需要类似的运算符操作,此时也可以重新定义这些运算符的功能,使其支持特定类型,完成特定的操作。
运算符重载函数的格式
返回值 operator 运算符(参数列表)
{
// 函数体
}
成员函数的格式:
给哪个类重载运算符,就把重载函数定义为哪个类的成员函数。
全局函数的格式:
需要在类内声明全局函数为友元函数。
成员函数版的运算符重载一定比全局函数版的运算符重载少一个参数,成员函数本身提供一个类对象。
运算符重载的目的、要求
目的:让自定义的类也能直接参与运算。
要求:
1、不能创造运算符,必须对已有的运算符重载;
2、不能更改运算符本身的功能,比如加法运算符“+”重载后实现乘法运算;
3、运算符重载本质上也是函数重载,但是不支持函数默认值设定;
4、不能改变重载后的运算符优先级和结合性,也不能改变运算符的操作数和语法结构。
算数运算符的重载
// 成员函数版#include <iostream>
using namespace std;class Complex
{int real;int virt;
public:Complex() { }Complex(int real, int virt) : real(real), virt(virt) { }void show(){cout << real << "+" << virt << "i" << endl;}Complex operator+(const Complex &other){Complex temp;temp.real = this->real + other.real;temp.virt = this->virt + other.virt;return temp;}
};int main()
{Complex com1(3,4);Complex com2(5,12);cout << "Com1: ";com1.show();cout << "Com2: ";com2.show();Complex com3 = com1 + com2;cout << "Com3: ";com3.show();return 0;
}
// 全局函数版#include <iostream>
using namespace std;class Complex
{int real;int virt;
public:Complex() { }Complex(int real, int virt) : real(real), virt(virt) { }void show(){cout << real << "+" << virt << "i" << endl;}friend Complex operator+(const Complex &c1, const Complex &c2);
};Complex operator+(const Complex &c1, const Complex &c2)
{Complex temp;temp.real = c1.real + c2.real;temp.virt = c1.virt + c2.virt;return temp;
}int main()
{Complex com1(3,4);Complex com2(5,12);cout << "Com1: ";com1.show();cout << "Com2: ";com2.show();Complex com3 = com1 + com2;cout << "Com3: ";com3.show();return 0;
}
赋值运算符的重载
#include <iostream>
using namespace std;class Complex
{int real;int virt;
public:Complex() { }Complex(int real, int virt) : real(real), virt(virt) { }void show(){cout << real << "+" << virt << "i" << endl;}Complex operator-=(const Complex &c1){this->real = this->real - c1.real;this->virt = this->virt - c1.virt;return *this;}
};int main()
{Complex com1(3,4);Complex com2(5,12);cout << "Com1: ";com1.show();cout << "Com2: ";com2.show();com2 -= com1; // 左调右参,com2 调用了混合运算符重载,参数是com1cout << "Com2: ";com2.show();return 0;
}
如果不手动编写赋值运算符(=)的重载,则赋值运算符重载会被编译器自动添加,见拷贝赋值函数。
当类中出现指针类型的成员变量时,默认的赋值运算符重载函数类名 &operator=(const 类名 &变量),也会产生类似于默认的浅拷贝构造函数的问题。因此也手动编写解决“浅拷贝”问题。
比较运算符的重载
// 成员函数版#include <iostream>
#include <iomanip>
using namespace std;class Complex
{float a;
public:Complex() { }Complex(float a):a(a) { }bool operator>=(Complex &other){return this->a >= other.a;}
};int main()
{Complex num1(15);Complex num2(6);cout << boolalpha << "num1 > num2?" << endl << num1.operator >=(num2) << endl;return 0;
}
// 全局函数版#include <iostream>
#include <iomanip>
using namespace std;class Complex
{float a;
public:Complex() { }Complex(float a):a(a) { }friend bool operator>=(Complex &a, Complex &b); // 友元
};bool operator>=(Complex &l, Complex &r)
{return l.a >= r.a;
}int main()
{Complex num1(15);Complex num2(6);cout << boolalpha << "num1 > num2?" << endl << operator >=(num1, num2) << endl;return 0;
}
() 运算符的重载
强转功能(只有成员函数版)
#include <iostream>
#include <iomanip>
using namespace std;class Complex
{float a;
public:Complex() { }Complex(float a):a(a) { }void show_int();operator int() // operator 类型(),强转功能重载的固定格式,只有成员函数版的重载函数{return this->a;}
};void Complex::show_int()
{cout << (int)this->a << endl; // 这里的 (int) 必须带着
}int main()
{Complex num1(15.7);
// Complex num2(6);cout << "(int)num1.a: ";num1.show_int();return 0;
}
伪函数(可重载)
#include <iostream>
#include <iomanip>
using namespace std;class Complex
{float a;
public:Complex() { }Complex(float a):a(a) { }void operator()() // 重载()运算符,调用函数功能的(),实现一个伪函数{cout << 250 << endl;}void operator()(string name){cout << name;}
};int main()
{Complex num1(15.7);
// Complex num2(6);num1.operator ()("He Yanwei is a ");num1.operator ()();return 0;
}
自增自减运算符的重载
// 成员函数版的前自增#include <iostream>
#include <iomanip>
using namespace std;class Complex
{int a;
public:Complex() { }Complex(float a):a(a) { }void show();Complex &operator++(){++this->a;return *this;}
};void Complex::show()
{cout << ++this->a << endl;
}int main()
{Complex num1(15);cout << "++num1.a: ";num1.show();return 0;
}
// 全局函数版后自减#include <iostream>
#include <iomanip>
using namespace std;class Complex
{int a;
public:Complex() { }Complex(float a):a(a) { }void show();friend Complex &operator--(Complex &com, int); // 必须是 int型 的哑元};void Complex::show()
{cout << (this->a)-- << endl;
}Complex &operator--(Complex &com, int)
{static Complex temp = com; // 使用 temp 获取自减前的值com.a--;return temp; // 返回自减前的值
}int main()
{Complex num1(17);Complex num2 = num1--;cout << "num1.a: ";num1.show();cout << "num2.a--: ";num2.show();return 0;
}
插入/提取运算符的重载
<<
// 全局函数实现提取运算符的重载#include <iostream>
using namespace std;class Complex
{int real;int virt;
public:Complex() { }Complex(int real, int virt) : real(real), virt(virt) { }void show(){cout << real << "+" << virt << "i" << endl;}friend ostream &operator<<(ostream &out, Complex &com);
};ostream &operator<<(ostream &out, Complex &com)
{out << com.real << "+" << com.virt << "i" << endl;return out;
}int main()
{Complex num1(17, 4);cout << "num1: ";operator<<(cout, num1); // 会返回一个 cout 继续输出// cout 是 ostream 类的类对象,不能自定义,但是可以通过引用 传入函数 再返回// cout << a << b; // 先输出a,再输出b // operator<<(cout, a)<<breturn 0;
}
>>
// 全局函数实现插入运算符的重载#include <iostream>
using namespace std;class Complex
{int real;int virt;
public:Complex() { }Complex(int real, int virt) : real(real), virt(virt) { }void show(){cout << real << "+" << virt << "i" << endl;}friend ostream &operator<<(ostream &out, Complex &com);friend istream &operator>>(istream &in, Complex &com);
};ostream &operator<<(ostream &out, Complex &com)
{out << com.real << "+" << com.virt << "i" << endl;return out;
}
istream &operator>>(istream &in, Complex &com)
{in >> com.real >> com.virt;return in;
}int main()
{Complex num1(17, 4);cout << "num1: ";operator<<(cout, num1);Complex num2;operator>>(cin, num2);cout << "num2: ";operator<<(cout, num2);return 0;
}