-
基本概念
操作符重载就是一些具有特殊名称的函数,“operator操作符”,把已存在操作进行重新定义,针对自定义的类类型对象,完成自定义的运算功能. -
双目操作符重载: L#R
2.1 运算类的双目操作符:+ - …
–》表达式结果是右值,不能对表达式结果再赋值
–》左右操作数既可以是左值也可以是右值
–》具体实现方式有两种:
1)成员函数形式(左调右参)
L#R的表达式可以被编译器处理为L.operator#®的成员函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果。
2)全局函数形式(左右都参数)
L#R的表达式也可以被编译器处理为operator#(L,R)的全局函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果
注:可以使用friend关键字,将全局函数形式操作符重载函数,声明为类的友元,友元函数可以访问类中任何成员。2.2 赋值类的双目操作符:+= -= …
–》表达式结果是左值,就是左操作数的自身
–》左操作数必须是左值,右操作数左值或右值又可以
–》具体实现方式有两种:
1)成员函数形式
L#R ==> L.operator#(R)
2)全局函数形式
L#R ==> operator#(L,R) -
单目操作符重载:#O
1.1 运算类单目操作符:-(负) ~(取反)
–》表示结果是右值,不能对表达式结果再赋值
–》操作数可以是左值也可以是右值
–》具体实现方式有两种:
1)成员函数形式
#O ==> O.operator#()
2)全局函数形式
#O ==> operator#(O)1.2 自增减单目操作符:++ –
1)前缀自增减
–》表达式结果是左值,就是操作数自身
–》操作数一定是左值
–》两种实现方式:
成员函数形式:#O ==> O.operator#()
全局函数形式:#O ==> operator#(O)2)后缀自增减
–》表达式结果是右值,是操作数自增减之前的数值
–》操作数一定是左值
–》两种实现方式:
成员函数形式:O# ==> O.operator#(int/*哑元*/)
全局函数形式:O# ==> operator#(O,int/*哑元*/) -
输出(插入)和输入(提取)操作符重载:<< >>
功能:实现自定义类型对象的直接输出或输入
注:ostream和istream是标准库的类,不能直接修改,所以重载时只能选择全局函数形式.#include
ostream//标准输出流类,cout是ostream类型的对象
istream//标准输入流类,cin是istream类型的对象//输出操作符重载函数
friend ostream& operator<<(ostream& os,const Right& r){
…
return os;
}
//输入操作符重载函数
friend istream& operator>>(istream& is,Right& r){
…
return is;
}//全局函数:operator<<(cout,a)
cout << a << …;//全局函数:operator>>(cin,a)
cin >> c >>…; -
练习:实现一个3*3矩阵类,支持如下操作符重载
+ - += -= -(负) 前后++、-- <<
* *=
提示:
class M33{
public:
private:
int m_a[3][3];
};1 2 3 9 8 7 10 10 10 4 5 6 + 6 5 4 = 10 10 10 7 8 9 3 2 1 10 10 10 1 2 3 9 8 7 -8 -6 -4 4 5 6 + 6 5 4 = -2 0 2 7 8 9 3 2 1 4 6 8 1 2 3 9 8 7 30 24 18 4 5 6 * 6 5 4 = 84 69 54 7 8 9 3 2 1 138 114 90
#include <iostream> #include <cstring> #include <cstdio> using namespace std; class M33{ public: M33(void){ memset((void *)m_a, 0, sizeof(int)*3*3); } M33(int a[][3]){ memcpy((void *)m_a, (void *)a, sizeof(int)*3*3); } //输出操作符重载:<< friend ostream& operator<<(ostream& os,const M33& m){ for(int i=0;i<3;i++){ for(int j=0;j<3;j++) os << m.m_a[i][j] << ' '; cout << endl; } return os; } //+ const M33 operator+(const M33& m) const{ int a[3][3] = {0}; for(int i=0;i<3;i++) for(int j=0;j<3;j++) a[i][j]=m_a[i][j]+m.m_a[i][j]; //M33 res(a); //return res; return a; } //- const M33 operator-(const M33& m) const{ int a[3][3] = {0}; for(int i=0;i<3;i++) for(int j=0;j<3;j++) a[i][j]=m_a[i][j]-m.m_a[i][j]; M33 res(a); return res; } //* const M33 operator*(const M33& m) const{ int a[3][3] = {0}; for(int i=0;i<3;i++) for(int j=0;j<3;j++) for(int k=0;k<3;k++) a[i][j]+=m_a[i][k]*m.m_a[k][j]; M33 res(a); return res; } //+= //m1+=m2 ==> m1=m1+m2 M33& operator+=(const M33& m){ *this = *this + m; return *this; } //-= M33& operator-=(const M33& m){ *this = *this - m; return *this; } //*= M33& operator*=(const M33& m){ *this = *this * m; return *this; } //-(负) const M33 operator-(void)const{ //M33 m; //return m - *this; return M33() - *this; } //前++,-- M33& operator++(void){ for(int i=0;i<3;i++) for(int j=0;j<3;j++) ++m_a[i][j]; return *this; } M33& operator--(void){ for(int i=0;i<3;i++) for(int j=0;j<3;j++) --m_a[i][j]; return *this; } //后++,-- const M33 operator++(int){ M33 old = *this; ++(*this); return old; } const M33 operator--(int){ M33 old = *this; --(*this); return old; } private: int m_a[3][3]; }; int main(void){ int a1[3][3] = {1,2,3,4,5,6,7,8,9}; int a2[3][3] = {9,8,7,6,5,4,3,2,1}; M33 m1(a1); M33 m2(a2); cout << m1 << endl; cout << m2 << endl; cout << "m1+m2:" << endl; cout << m1+m2 << endl;//m1.operator+(m2) cout << "m1-m2:" << endl; cout << m1-m2 << endl;//m1.operator-(m2) cout << "m1*m2:" << endl; cout << m1*m2 << endl;//m1.operator*(m2) cout << "m1+=m2:" << endl; cout << (m1+=m2) << endl; cout << m1 << endl; cout << "m1-=m2:" << endl; cout << (m1-=m2) << endl; cout << m1 << endl; cout << "m1*=m2:" << endl; cout << (m1*=m2) << endl; cout << m1 << endl; cout << "-m2:" << endl; cout << -m2 << endl; cout << "++m2:" << endl; cout << ++m2 << endl; cout << m2 << endl; cout << "--m2:" << endl; cout << --m2 << endl; cout << m2 << endl; cout << "m2++:" << endl; cout << m2++ << endl; cout << m2 << endl; cout << "m2--:" << endl; cout << m2-- << endl; cout << m2 << endl; return 0; }
-
下标操作符重载:[]
功能:实现自定义类型对象能够像数组一样使用
注:非const对象返回左值,常对象返回右值
string str = “…”
//str.operator == ‘A’
str[i] = ‘A’;const string str = “…”
//str.operator == ‘A’
str[i] = ‘A’;//error#include <iostream> using namespace std; //模拟容器类:里面可以存放若干个int数据 class Array{ public: Array(size_t size){ m_arr = new int[size]; } ~Array(void){ delete[] m_arr; } //下标操作符重载:[] int& operator[](size_t i){ cout << "匹配非const对象" << endl; return m_arr[i]; } const int& operator[](size_t i)const{ cout << "匹配const对象" << endl; return m_arr[i]; } private: int* m_arr; }; int main(void){ Array arr(10); arr[0] = 123;//arr.operator[](0) = 123 cout << arr[0] << endl;//123 const Array& arr2 = arr; //arr2[0] = 321;//应该error cout << arr2[0] << endl;//123 return 0; }
-
函数操作符: ()
功能:实现让自定义类型的对象像函数一样去使用//仿函数
注:对参数个数、类型和返回值没有任何限制
A a(…);
a(100,1.23);//a.operator()(100,1.23)#include <iostream> using namespace std; class Func{ public: int operator()(int i,int j){ return i * j; } int operator()(int i){ return i * i; } }; int main(void){ Func func;//仿函数 //func.operator()(100,200) cout << func(100,200) << endl;//20000 //func.operator()(100) cout << func(100) << endl;//10000 return 0; }
-
new和delete操作符重载
static void* operator new(size_t size){…}
static void operator delete(void* p){…}#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 << "分配内存" << endl; void* pv = malloc(size); return pv; } static void operator delete(void* pv){ cout << "释放内存" << 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; pa = NULL; return 0; }
-
操作符重载的限制
1)不是所有的操作符都能重载,不能重载的操作符如下:
作用域限定操作符::
直接成员访问操作符.
直接成员指针解引用操作符.*
条件操作符? :
字节长度操作符sizeof
sizeof里的表达式不会被计算,如sizeof(a=b),执行完之后a并不会等于b
类型信息操作符typeid
2)如果一个操作符所有的操作数都是基本类型,则无法重载
3)操作符重载不会改变编译器预定义的优先级
4)操作符重载不会改变操作符的个数
5)无法通过操作符重载发明新的符号,如operator@,本身@就不是操作符,所以不可重载
6)只能使用成员函数形式重载操作符
=
[]
()
->
C++学习之操作符重载
最新推荐文章于 2022-10-29 21:57:52 发布