C++学习笔记(七)

二十.操作符重载(operator)

2.双目操作符重载: L#R(L:左操作数;R:右操作数)

2.1 运算类的双目操作符:+ -

①表达式结果是右值,不能对表达式结果再赋值(加const,不能加引用&)
②左右操作数既可以是左值也可以是右值
③具体实现方式有两种:

1)成员函数形式(左调右参:左操作数c1作为调用对象,右操作数c2是参数对象) 	
a. 成员函数定义在类里面。
b. L#R的表达式可以被编译器处理为L.operator#(R)的成员函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果。
eg.
//重载+:成员函数形式
//c1+c2 ==> c1.operator+(c2)
2)全局函数形式(左右操作数c1,c2都是参数)
a. 假如全局函数定义在类外,若想访问到类中的成员变量,需要在类中用friend关键字声明下全局函数。也可以把友元函数直接定义在类的内部,但是其本质还是属于全局函数,并不属于类。
b. L#R的表达式也可以被编译器处理为operator#(L,R)的全局函数调用形式,由该函数实现自定义的运算功能,其返回结果就是表达式的结果
(注:可以使用friend关键字,将全局函数形式操作符重载函数,声明为类的友元,友元函数可以访问类中任何成员。)
eg.
//重载-:全局函数形式
//c2-c1 ==> operator-(c2,c1)

eg.

#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)
    //1)第一个const:修饰返回值,禁止对表达式结果再赋值
    //2)第二个const:常引用,支持常量型右操作数
    //3)第三个const:常成员函数,支持常量型左操作数
    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& left,const Complex& right);
};
//重载-:全局函数形式
//c2-c1 ==> operator-(c2,c1)
const Complex operator-(
    const Complex& left,const Complex& right){
    Complex res(left.m_r-right.m_r,
                left.m_i-right.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
    Complex c4 = c2 - c1;
    c4.print();//2+2i

    return 0;
}

2.1 赋值类的双目操作符:+= -=

①表达式结果是左值,就是左操作数的自身(不加const,加引用&)
②左操作数必须是左值,右操作数左值或右值都可以
③具体实现方式有两种:

1)成员函数形式
L#R ==> L.operator#(R)
2)全局函数形式
L#R ==> operator#(L,R)

eg.

#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; // 返回自身
    }
    //-=:全局函数形式
    //c1-=c2 ==> operator-=(c1,c2)
    //可以把友元函数直接定义在类的内部,但是其本质还是属于全局函数,并不属于类. 
    friend Complex& operator-=(
            Complex& left,const Complex& right){
        left.m_r -= right.m_r;
        left.m_i -= right.m_i;
        return left; //返回左操作数的自身
    }
private:
    int m_r;//实部
    int m_i;//虚部
};
int main(void){
    Complex c1(1,2);
    Complex c2(3,4);
    c1 += c2;
    c1.print();//4+6i
    Complex c3(5,6);
    (c1 += c2) = c3;
    c1.print();//5+6i

    c1 -= c2;
    c1.print();//2+2i
    (c1 -= c2) = c3;
    c1.print();//5+6i

    return 0;
}

3.单目操作符重载:#O

3.1 运算类单目操作符:-(负) ~

①表示结果(-a )是右值,不能对表达式结果再赋值(加const,不能加引用&)
②操作数可以是左值也可以是右值
③具体实现方式有两种:

1)成员函数形式
#O ==> O.operator#()
2)全局函数形式
#O ==> operator#(O)

eg.

#include <iostream>
using namespace std;
class Integer{
public:
    Integer(int i=0):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;//operator~(i);
    j.print();//10000

    return 0;
}

3.2 自增减单目操作符:++ - -

3.2.1 前缀自增减
①表达式结果是左值,就是操作数自身
②操作数一定是左值
③两种实现方式:

成员函数形式:#O ==> O.operator#()
全局函数形式:#O ==> operator#(O)

eg.

//前++:成员函数形式
//++i ==> i.operator++();
Integer& operator++(void){
    ++m_i;
    return *this;
}
//前--:全局函数形式
//--i ==> operator--(i);
friend Integer& operator--(Integer& i){
    --i.m_i;
    return i;
}

3.2.2 后缀自增减
①表达式结果是右值,是操作数自增减之前的数值
②操作数一定是左值
③两种实现方式:

成员函数形式:O# ==> O.operator#(int/*哑元*/)
全局函数形式:O# ==> operator#(O,int/*哑元*/)

eg.

//后++:成员函数形式
//i++ ==> i.operator++(0/*哑元*/)
const Integer operator++(int/*哑元*/){
    Integer old = *this;
    ++(*this);//++m_i;
    return old;
}
//后--:全局函数形式
//i-- ==> operator--(i,0/哑元/)
friend const Integer operator--(Integer& i,int/*哑元*/){
    Integer old = i;
    --i;//--i.m_i;
    return old;
}

eg.

#include <iostream>
using namespace std;
class Integer{
public:
    Integer(int i=0):m_i(i){}
    void print(void) const {
        cout << m_i << endl;
    }
    //前++:成员函数形式
    //++i ==> i.operator++();
    Integer& operator++(void){
        ++m_i;
        return *this;
    }
    //前--:全局函数形式
    //--i ==> operator--(i);
    friend Integer& operator--(Integer& i){
        --i.m_i;
        return i;
    }
    //后++:成员函数形式
    //i++ ==> i.operator++(0/*哑元*/)
    const Integer operator++(int/*哑元*/){
        Integer old = *this;
        ++(*this);//++m_i;
        return old;//返回自增加之前的数值
    }
    //后--:全局函数形式
    //i-- ==> operator--(i,0/哑元/)
    friend const Integer operator--(Integer& i,int/*哑元*/){
        Integer old = i;
        --i;//--i.m_i;
        return old;//返回自增减之前的数值
    }
private:
    int m_i;
};
int main(void){
    Integer i(100);
    Integer j = ++i;
    i.print();//101
    j.print();//101
    j = ++++i;
    i.print();//103
    j.print();//103
    
    j = --i;
    i.print();//102
    j.print();//102
    j = ----i;
    i.print();//100
    j.print();//100
    
    j = i++;
    i.print();//101
    j.print();//j保存的是i++的表达式结果,所以是100

    j = i--;
    i.print();//100
    j.print();//同理j保存的是表达式结果,为101

    return 0;
}

4.输出(插入)和输入(提取)操作符重载:<< >>

功能:实现自定义类型对象的直接输出或输入

(注:ostream和istream是标准库的类,不能直接修改,所以重载时只能选择全局函数形式)

#include <iostream>
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;
}
(PS:以后用上面这段代码时,直接往里面套,把Right换成类名就行,注意输出中有const,输入中没有const)

//全局函数:operator<<(cout,a)
cout << a << ...;

//全局函数:operator>>(cin,a)
cin >> c >>...;

eg.

#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){
        cout << "请输入实部:";
        is >> c.m_r;
        cout << "请输入虚部:";
        is >> c.m_i;
        return is;
    }
private:
    int m_r;//实部
    int m_i;//虚部
};
int main(void){
    Complex c1(1,2);
    Complex c2(3,4);
    //operator<<(cout,c1)
    cout << c1 << endl;
    cout << c1 << ',' << c2 << endl;

    Complex c3(0,0);
    //operator>>(cin,c3)
    cin >> c3;
    cout << "c3:" << c3 << endl;

    return 0;
}

练习

练习:实现一个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

eg.

#include <iostream>
using namespace std;

class M33
{
public:
	//初始化数组为0,无参构造
	//M33(void)
	//{
	//	for (int i = 0; i < 3; i++)
	//	{
	//		for (int j = 0; j < 3; j++)
	//		{
	//			aa[i][j] = 0;
	//		}
	//	}
	//}

	//有参构造
	M33(int a[][3])
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				aa[i][j] = a[i][j];
			}
		}
	}

	//输出操作符重载: <<
	//用来显示3*3矩阵
	friend ostream& operator<<(ostream& os, const M33& arr)
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				os << arr.aa[i][j] << " ";
			}
			os << endl;
		}
		return os;
	}

	//重载+:成员函数形式
	//c1+c2 ==> c1.operator+(c2)
	//1)第一个const:修饰返回值,禁止对表达式结果再赋值
	//2)第二个const:常引用,支持常量型右操作数
	//3)第三个const:常成员函数,支持常量型左操作数
	const M33 operator+(const M33& c) const 
	{	
		int a[3][3] = { 0 };
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				a[i][j] = aa[i][j] + c.aa[i][j];
			}
		}
		M33 add(a);
		return add;
	}

	//重载-:成员函数形式
	const M33 operator-(const M33& c) const
	{
		int a[3][3] = { 0 };
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				a[i][j] = aa[i][j] - c.aa[i][j];
			}
		}
		M33 sub(a);
		return sub;
	}

	//+=:成员函数形式
	//c1+=c2 ==> c1.operator+=(c2)
	M33& operator+=(const M33& c)
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				aa[i][j] += c.aa[i][j];
			}
		}
		return *this; // 返回自身
	}
	//-=:成员函数形式
	//c1-=c2 ==> operator-=(c1,c2)
	M33& operator-=(const M33& c)
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				aa[i][j] -= c.aa[i][j];
			}
		}
		return *this; // 返回自身
	}

	//-(负):成员函数形式
	const M33 operator-(void) const
	{
		int a[3][3] = { 0 };
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				a[i][j] = 0 - aa[i][j];
			}
		}
		M33 neg(a);
		return neg;
	}

	//前++:成员函数形式
	//++i ==> i.operator++();
	M33& operator++(void) 
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				++aa[i][j];
			}
		}
		return *this;
	}

	//前--:全局函数形式
	//--i ==> operator--(i);
	M33& operator--(void) 
	{
		for (int i = 0; i < 3; i++)
		{
			for (int j = 0; j < 3; j++)
			{
				--aa[i][j];
			}
		}
		return *this;
	}

	//后++:成员函数形式
	//i++ ==> i.operator++(0/*哑元*/)
	const M33 operator++(int/*哑元*/) 
	{
		M33 old = *this;
		++(*this);//++m_i;
		return old;
	}

	//后--:全局函数形式
	//i-- ==> operator--(i,0/哑元/)
	friend const M33 operator--(M33& i, int/*哑元*/) 
	{
		M33 old = i;
		--i;//--i.m_i;
		return old;
	}

private:
	int aa[3][3];
};

int main(void)
{
	int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int b[3][3] = { 9,8,7,6,5,4,3,2,1 };
	M33 a1(a);
	M33 a2(b);
	cout << a1 << endl;
	cout << a2 << endl;
	
	cout << "a1+a2:" << endl;
	cout << a1+a2 << endl;

	cout << "a1-a2:" << endl;
	cout << a1 - a2 << endl;

	cout << "a1+=a2:" << endl;
	cout << (a1 += a2) << endl; 
	cout << "a1:" << endl;
	cout << a1 << endl;

	cout << "a1-=a2:" << endl;
	cout << (a1 -= a2) << endl;
	cout << "a1:" << endl;
	cout << a1 << endl;

	cout << "-a2:" << endl;
	cout << -a2 << endl;

	cout << "++a2:" << endl;
	cout << ++a2 << endl;
	cout << a2 << endl;

	cout << "--a2:" << endl;
	cout << --a2 << endl;
	cout << a2 << endl;

	cout << "a2++:" << endl;
	cout << a2++ << endl;
	cout << a2 << endl;

	cout << "a2--:" << endl;
	cout << a2-- << endl;
	cout << a2 << endl;
	return 0;
}

5.下标操作符重载:[]

功能:实现自定义类型对象能够像数组一样使用
(注:非const对象返回左值,常对象返回右值)

string str = "..."
//str.operator[](i) == 'A'
str[i] = 'A';

eg.string str = "zhangsan";
str.operator[](0) = 'Z';
str[0] = 'Z'; //和上面等价
--------------------
const string str = "..."
//str.operator[](i) == 'A'
str[i] = 'A';//error

eg.

#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;
}

6.函数操作符: ()

功能:实现让自定义类型的对象像函数一样去使用//仿函数
(注:对参数个数、类型和返回值没有任何限制)

A a(...);
a(100,1.23);//a.operator()(100,1.23)

eg.

#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;
}

7.new和delete操作符重载(了解)

static void* operator new(size_t size){...}
static void operator delete(void* p){...}

eg.

#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;
}

8.操作符重载限制

①不是所有操作符都能重载,下面操作符不能重载:
---》作用域限定操作符 "::"
---》直接成员访问操作符 "."
---》直接成员指针解引用操作符 ".*"
---》条件操作符 "?:"
---》字节长度操作符 "sizeof"
---》类型信息操作符 "typeid"//后面讲
②如果一个操作符所有的操作数都是基本类型,则无法重载
③操作符重载不会改变编译器预定义的优先级
④操作符重载不会改变操作数个数
⑤无法通过操作符重载发明新的符号
⑥只能使用成员函数形式重载操作符
    = [] () ->	 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boss-dog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值