文章目录
操作符重载
双目操作符
计算类的双目操作符(’+‘和’-’)
- 表达式的结果是右值。
- 左右操作数既可以是左值也可以是右值。
- 两种实现方式:
- 成员函数形式(左调右参)
L#R的表达式可以被编译器处理成 L.operator#®的成员函数调用形式,该函数的返回值就是表达式的结果。 - 全局函数形式(左右操作数都作为参数)
L#R的表达式也可以被成立成::operator#(L,R)的全局函数调用形式,该函数的返回值就是表达式的结果。 - 注:使用friend关键字,可以把一个全局函数声明为某个类的友元,友元函数可以访问类中的任何成员。
- 成员函数形式(左调右参)
代码示例
- complex.cpp
#include <iostream>
using namespace std;
class Complex{
public:
Complex(int r,int i):m_r(r),m_i(i){}
void print(void)const{
cout << m_r << '+' << m_i << 'i'
<< endl;
}
//"+"操作符重载函数(成员函数形式)
//c1 + c2==>c1.operator+(c2)
//三个const作用
//1)修饰返回值,禁止对表达式赋值,返回右值
//2)常引用参数,为了支持常量型右操作数
//3)常成员函数,为了支持常量型左操作数
const Complex operator+(
const Complex& c)const{
Complex res(m_r+c.m_r,m_i+c.m_i);
return res;
}
private:
int m_r;//实部
int m_i;//虚部
//友元,可以访问类中私有成员
friend const Complex operator-(
const Complex& l,const Complex& r);
};
//"-"操作符重载函数,全局函数形式
const Complex operator-(
const Complex& l,const Complex& r){
Complex res(l.m_r-r.m_r , l.m_i-r.m_i);
return res;
}
int main(void)
{
const Complex c1(1,2);
const Complex c2(3,4);
c1.print();
c2.print();
//Complex c3 = c1.operator+(c2);
Complex c3 = c1 + c2;
c3.print();//4+6i
//(c1 + c2) = c3;//应该error
//c3 = ::operator-(c2,c1)
c3 = c2 - c1;
c3.print();//2+2i
return 0;
}
- 执行结果
赋值类的双目操作符(+=、-=)
- 表达式结果是左值,就是左操作数的自身。
- 左操作数一定是左值,右操作数可以是左值也可以是右值。
- 两种实现方式:
- 成员函数形式
L#R ⇒ L.operator#® - 全局函数形式
L#R ⇒ ::operator#(L,R)
- 成员函数形式
代码示例
- complex.cpp
#include <iostream>
using namespace std;
class Complex{
public:
Complex(int r,int i):m_r(r),m_i(i){}
void print(void)const{
cout << m_r << '+' << m_i << 'i'
<< endl;
}
//"+="成员函数形式
//c1+=c2==>c1.operator+=(c2)
Complex& operator+=(const Complex& c){
m_r += c.m_r;
m_i += c.m_i;
return *this;
}
//"-="全局函数形式
//友元函数可以直接定义在类的内部,但本质
//还是全局函数
friend Complex& operator-=(
Complex& l,const Complex& r){
l.m_r -= r.m_r;
l.m_i -= r.m_i;
return l;
}
private:
int m_r;//实部
int m_i;//虚部
};
int main(void)
{
Complex c1(1,2);
Complex c2(3,4);
c1 += c2;//c1.operator+=(c2)
c1.print();//4+6i;
c1 -= c2;//operator-=(c1,c2)
c1.print();//1+2i
return 0;
}
- 执行结果
单目操作符
计算类单目操作符(-(取负)、~(取反))
- 表达式结果是右值,不能对表达式进行赋值操作
- 操作数只有一个,可以左值也可以右值
- 两种实现形式
- 成员函数形式
#O ⇒ O.operator#(); - 全局函数形式
#O ⇒ ::operator#(O);
- 成员函数形式
代码示例
- integer.cpp
#include <iostream>
using namespace std;
class Integer{
public:
Integer(int i):m_i(i){}
void print(void)const{
cout << m_i << endl;
}
//"-":成员函数形式
const Integer operator-(void) const {
Integer res(-m_i);
return res;
}
//"~":全局函数形式(自定义表示乘方)
friend const Integer operator~(
const Integer& i){
Integer res(i.m_i * i.m_i);
return res;
}
private:
int m_i;
};
int main(void)
{
Integer i(100);
Integer j = -i;//i.operator-()
j.print();//-100
j = ~i;
j.print();//10000
return 0;
}
- 执行结果
自增减单目操作符(++、–)
- 前++、–
- 表达式的结果是左值,就是操作数自身
- 操作数一定是左值
- 两种实现形式
- 成员函数形式
#O ⇒ O.operator#(); - 全局函数形式
#O ⇒ ::operator#(O);
- 成员函数形式
- 后++、–
- 表达式的结果是右值,是操作数自增减前的副本
- 操作数也一定是左值
- 两种实现形式
- 成员函数形式
O# ⇒ O.operator#(int); - 全局函数形式
O# ⇒ ::operator#(O,int);
- 成员函数形式
- 注:后缀自增减操作符函数中增加了一个int哑元参数,用于和前缀自增减进行区分。
代码示例
- integer.cpp
#include <iostream>
using namespace std;
class Integer{
public:
Integer(int i):m_i(i){}
void print(void)const{
cout << m_i << endl;
}
//前++:成员函数形式
Integer& operator++(void){
++m_i;
return *this;
}
//前--:全局函数形式
friend Integer& operator--(Integer& i){
--i.m_i;
return i;
}
//后++:成员函数形式
const Integer operator++(int){
Integer old = *this;
++m_i;//++(*this)
return old;
}
//后--:全局函数形式
friend const Integer operator--(
Integer& i,int){
Integer old = i;
--i.m_i;//--i
return old;
}
private:
int m_i;
};
int main(void)
{
Integer i(100);
Integer j = ++i;//i.operator++()
j.print();//101
i.print();//101
j = ++++i;//i.operator++().operator++()
j.print();//103
i.print();//103
j = --i;//operator--(i);
j.print();//102
i.print();//102
j = ----i;
j.print();//100
i.print();//100
j = i++;//i.operator++(0/*哑元*/)
j.print();//100
i.print();//101
j = i--;//operator--(i,0)
j.print();//101
i.print();//100
return 0;
}
- 执行结果
插入(输出)和提取(输入)操作符(’<<’ 和 ‘>>’)
功能:实现自定义类型直接的输入和输出
- 注:只能使用全局函数形式(friend)
#include <iostream>
-->ostream cout;
-->istream cin;
friend ostream& operator<<(
ostream& os,const RIGHT& right){...}
friend istream& operator>>(
istream& is,RIGHT& right){...}
//全局函数:operator<<(cout,a)
cout << a;
cout << c << ...
//全局函数:operator>>(cin,a)
cin >> a;
cin >> c << ...
代码示例
- io_operator.cpp
#include <iostream>
using namespace std;
class Complex{
public:
Complex(int r,int i):m_r(r),m_i(i){}
//<<:只能使用全局函数形式
friend ostream& operator<<(
ostream& os,const Complex& c){
os << c.m_r << '+' << c.m_i << 'i';
return os;
}
//>>:只能使用全局函数形式
friend istream& operator>>(
istream& is,Complex& c){
is >> c.m_r >> c.m_i;
return is;
}
private:
int m_r;//实部
int m_i;//虚部
};
int main(void)
{
Complex c1(1,2);
Complex c2(3,4);
cout << c1 << endl;
cout << c1 << ',' << c2 << endl;
cout << "请输入一个复数" << endl;
cin >> c1;
cout << c1 << endl;
return 0;
}
- 执行结果
下标操作符(’[]’)
功能:让一个对象可以像数组一样去使用。
- 注:非常对象返回左值,常对象返回右值。
string s = "hello";
s[0] = 'H';//s.operator[](0) = 'H';
const string s2 = "hello";
s2[0] = 'H';//error
代码示例
- array_operator.cpp
#include <iostream>
using namespace std;
//容器类,里面可以存放若干个整形数
class Array{
public:
//Array(size_t size)
// :m_arr(new int[size]),m_size(size){}
Array(size_t size){
m_arr = new int[size];
m_size = size;
}
//非常对象调用,返回左值
int& operator[](size_t i){
return m_arr[i];
}
//常对象调用,返回右值
const int& operator[](size_t i)const{
return m_arr[i];
}
private:
int* m_arr;
size_t m_size;
};
int main(void)
{
Array arr(3);
arr[0] = 10;//arr.operator[](0)
arr[1] = 20;
arr[2] = 30;
const Array& rarr = arr;
cout << rarr[0] << endl;
cout << rarr[1] << endl;
cout << rarr[2] << endl;
return 0;
}
- 执行结果
函数操作符(’()’)
功能:让对象像函数一样去使用
- 注:对参数个数、类型和返回值类型没有限制。
class A{};
A a;
a(10,1.23);//a.operator()(10,1.23);
代码示例
- func_operator.cpp
#include <iostream>
using namespace std;
class Func{
public:
double operator()(double x){
return x*x;
}
int operator()(int x,int y){
return x+y;
}
};
int main(void)
{
Func func;
//func.operator()(3.3)
cout << func(3.3) << endl;//10.89
//func.operator()(10,20)
cout << func(10,20) << endl;//30
return 0;
}
- 执行结果
new/delete 操作数
static void* operator new(size_t size){..}
static void operator delete(void *p){..}
代码示例
- new.cpp
#include <iostream>
#include <cstdlib>
using namespace std;
class A{
public:
A(void){
cout << "A的构造函数" << endl;
}
~A(void){
cout << "A的析构函数" << endl;
}
static void* operator new(size_t size){
cout << "A::new" << endl;
void* pv = malloc(size);
return pv;
}
static void operator delete(void *pv){
cout << "A::delete" << endl;
free(pv);
}
};
int main(void)
{
//1)A* pa=(A*)A::operator new(sizeof(A))
//2)pa->构造函数
A* pa = new A;
//1)pa->析构函数
//2)A::operator delete(pa)
delete pa;
return 0;
}
- 执行结果
- 不是所有的操作符都能重载,以下操作符不能重载:
- 作用域限定操作符(::)
- 直接成员访问操作符(.)
- 直接成员指针解引用操作符(.*)
- 条件操作符(?:)
- 字节长度操作符(sizeof)
- 类型信息操作符(typeid)
- 如果一个操作符所有操作数都是基本类型,则该操作符无法重载。
- 操作符重载不会改变编译器预定义的优先级
- 操作符重载无法改变操作数的个数
- 无法通过操作符重载发明新的符号
- 只能使用成员形式不能使用全局形式的操作符(= 、()、->)