运算符重载

1. 运算符重载

是指赋于基本运算符新的运算,使之能应用于自定义的类型的运算(类类型),实际上是将运算符强制修饰为函数的形式

例如:

C语言:
			运算符:+
				10+20  //实现两个数据(基本的数据类型)相加
				10.5+20
		C++:
			运算符:+
				People+Animal  //People类类型、Animal类类型
				Peoson+Test

2. 可以被重载的运算符

运算符重载: 本质上是给类定义运算操作,将类运算符强制修饰为函数(operator),将类的运算符操作变成函数操作。

可以被重载的运算符:

算术运算符:+、-、*、/、%、++、--

位操作运算符:&、|、~、^(位异或)、>(右移)

逻辑运算符:!、&&、||

比较运算符:<=、>=、等等

赋值运算符:=、+=、-=、*=、/=、%=、&=、|=、^=、>=

其他运算符:[]、()、->、,、new、delete、new[]、delete[]、*指针运算符

注意事项:

A、除成员访问运算符“.”、作用域运算符“::”、sizeof运算符和三目运算符“?:”以外,C++中的所有运算符都可 以重载(其中“=”和“&”不必用户重载)

B、重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符

C、运算符重载的实质是函数重载,遵循函数重载的选择原则

D、重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构

E、运算符重载不能改变该运算符用于内部类型对象的含义

F、运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符

G、重载运算符的函数不能有默认的参数,否则就改变了运算符的参数个数

H、重载的运算符只能是用户自定义类型,否则就不是重载而是改变了现有的C++标准数据类型的运算符的规则

I、运算符重载可以通过成员函数的形式,也可是通过友元函数,还可以是非成员非友元的普通函数。

2.1 成员函数运算符重载

对于成员函数运算符重载至少一个参数是隐含的即调用对象的指针。然而,并非所有的运算符重载都要求两个参数。

例如,对于一元运算符(例如重载的前缀递增运算符 ++),只需要一个参数即隐含的 this 指针。对于二元运算符(例如重载的加法运算符 +),你可能会定义两个参数一个是隐含的 this 指针,另一个是运算符右侧的操作数。

细节:一元运算符重载 和  二元运算符重载

举例

#include <iostream>

class MyClass {
public:
    int data;

    // 一元运算符重载
    MyClass operator++() {
        data++;
        return *this;
    }

    // 二元运算符重载
    MyClass operator+(const MyClass& other) {
        MyClass result;
        result.data = this->data + other.data;
        return result;
    }
};

int main() {
    MyClass obj1;
    obj1.data = 10;

    // 一元运算符重载
    ++obj1;
    std::cout << "After unary operator overload: " << obj1.data << std::endl;

    MyClass obj2;
    obj2.data = 5;

    // 二元运算符重载
    MyClass result = obj1 + obj2;
    std::cout << "After binary operator overload: " << result.data << std::endl;

    return 0;
}

问题:

(1)你举得例子中那个二元运算符重载形参other接受的实参是不是obj2

是的,你理解得正确。在我提供的例子中,operator+ 的形参 other 接受的实参是 obj2。在表达式 obj1 + obj2 中,obj1 被隐含地传递给 this 指针,而 obj2 作为实参传递给 other。在函数内部,通过这两个对象的数据执行了加法操作,并返回了结果。

MyClass operator+(const MyClass& other) {
    MyClass result;
    result.data = this->data + other.data;
    return result;
}

在这里,other 是对 obj2 的引用,所以在函数内可以通过 other.data 访问到 obj2 的数据。

(2)你举得例子中那个一元运算符重载实参obj1传递给了谁?

在我提供的例子中,一元运算符重载中的实参 obj1 被隐含地传递给了该运算符函数的调用对象,即通过 this 指针传递给了成员函数。

在举例

MyClass operator-() {
    MyClass result;
    result.data = -this->data;
    return result;
}

在这里,当你使用 -obj1 的表达式时,obj1 被隐含地传递给了一元运算符 - 重载函数。在函数内部,通过 this->data 访问了 obj1 的数据,并返回了相反数的结果。

2.1.1 运算符重载的格式:

关键字:operator

格式:

函数返回值类型     operator   重载的运算符   ([参数列表])//运算符重载,可以将operator和重载的运算符看成是函数名

{

//代码块

}

例如:
	void    operator   +   (int  b)
	{

	}

2.1.2 举例

override.cpp

#include "iostream"
using namespace std;

//成员函数运算符重载
class People {
public:
	void operator + (int a) {//运算符重载,重载+号
		cout << "相加的结果" << this->number + a << endl;
	}


	char operator + (char a) {//运算符重载,重载+号
		cout << "a=" << a << endl;
		return a;
	}

	int operator *(People& people) {
		return this->number * people.number;
	}

	int number = 40;
	//int number2 = 10;
};

int main()
{
	People people1;
	People people2;
	people1 + 50;//90  //相当于调用了运算符重载函数
	//50 + people1; //反过来就会报错  //因为我们使用了this指针,而this指针是默认作为函数的第一个参数的
	
	char ret = people1 + 'v';
	cout << "ret=" << ret << endl;

	cout << "结果=" << people1*people2 << endl;

	return 0;
}

2.2 友元函数运算符重载

关键字:friend 、 operator

格式:

friend   函数返回值类型   operator     重载的运算符   ([参数列表]);//运算符重载,可以将operator和重载的运算符看成是函数名

例如:
	friend    void    operator   +   (int  b);

override.cpp

//友元函数运算符重载
class People {
public:
	//声明友元函数
	friend int operator - (People& people, int a);

	int number = 40;
};

//友元函数
int operator - (People& people, int a) {
	return people.number - a;
}

int main()
{
	People people1;
	int res = people1 - 10;

	cout << "结果=" << res << endl;

	return 0;
}

//友元函数运算符重载
class People {
public:
	//声明友元函数
	friend int operator - (People& people, int a);

	int number = 40;
};

//友元函数
int operator - (People& people, int a) {
	return people.number - a;
}

int main()
{
	People people1;
	int res = people1 - 10;

	cout << "结果=" << res << endl;

	return 0;
}

2.3 练习1计算复数(实现   加   减    乘  )

override_test.cpp

#include "iostream"
using namespace std;


//计算复数(实现   加   减    乘  )
class Complex
{
public:
	Complex(int shi, int xu)//有参构造,给实部和虚部赋值
	{
		this->shi = shi;
		this->xu = xu;
	}
	Complex()//无参构造
	{

	}

	//虚数的加
	//Complex&  返回对象引用
	Complex& operator +(Complex& complex)//切记有个隐藏的this指针
	{
		//这里的Complex comp是局部变量,函数结束就会销毁,返回的话可能出现悬垂引用的问题
		//Complex comp;//实例对象
		//comp.shi = this->shi + complex.shi;
		//comp.xu = this->xu + complex.xu;
		//return comp;

		//这种 返回 避免了悬垂引用的问题  记得释放内存,这里不做演示了
		Complex* comp = new Complex;
		comp->shi = this->shi + complex.shi;
		comp->xu = this->xu + complex.xu;
		return *comp;
	}

	//虚数的减
	Complex& operator -(Complex& complex)
	{
		//这里的Complex comp是局部变量,函数结束就会销毁,返回的话可能出现悬垂引用的问题
		/*Complex comp;
		comp.shi = this->shi - complex.shi;
		comp.xu = this->xu - complex.xu;
		return comp;*/

		//这种 返回 避免了悬垂引用的问题
		Complex* comp = new Complex;
		comp->shi = this->shi - complex.shi;
		comp->xu = this->xu - complex.xu;
		return *comp;
	}

	//虚数的乘
	Complex& operator *(Complex& complex)
	{
		//这里的Complex comp是局部变量,函数结束就会销毁,返回的话可能出现悬垂引用的问题
		/*Complex comp;
		comp.shi = this->shi * complex.shi - this->xu * complex.xu;
		comp.xu = this->shi * complex.xu + complex.shi * this->xu;
		return comp;*/

		//这种 返回 避免了悬垂引用的问题
		Complex* comp = new Complex;
		comp->shi = this->shi * complex.shi - this->xu * complex.xu;
		comp->xu = this->shi * complex.xu + complex.shi * this->xu;
		return *comp;

	}

	//声明友元函数
	friend void print(Complex& complex);

private:
	int shi;
	int xu;
};

//友元函数
void print(Complex& complex)
{
	if (complex.xu < 0)
	{
		cout << "复数:" << complex.shi << complex.xu << "i" << endl;
		return;
	}
	cout << "复数:" << complex.shi << "+" << complex.xu << "i" << endl;
}
int main()
{
	//实例化对象,并给其赋值
	Complex complex1(10, 20);//10+20i
	Complex complex2(5, 50);//5+50i

	//开始验证  加  减  乘
	Complex complex;
	complex = complex1 + complex2;
	print(complex);

	complex = complex1 - complex2;
	print(complex);

	complex = complex1 * complex2;
	print(complex);


	return 0;
}

2.4 练习2

有两个矩阵a和b,均为2行3列,求两个矩阵之和。重载运算符"+” , 使之能用于矩阵相加。

override_test2.cpp

#include "iostream"
using namespace std;

//有两个矩阵a和b,均为2行3列,求两个矩阵之和。重载运算符"+” , 使之能用于矩阵相加。

class Matrix
{
public:
	Matrix() {//构造函数

	}	
	Matrix(int jz[2][3])//有参构造,给矩阵属性赋值
	{
		for (int i = 0; i < 2; i++)
			for (int j = 0; j < 3; j++)
				juzhen[i][j] = jz[i][j];
	}
	
	//声明友元函数
	friend Matrix operator+(Matrix& a, Matrix& b);

	//输出
	void print() //输出矩阵
	{
		for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 3; j++) {
				cout << juzhen[i][j] << " ";
			}
			cout << endl;
		}
	}

private:
	int juzhen[2][3]; //定义矩阵属性变量
};


//友元函数
Matrix operator+(Matrix& a, Matrix& b)
{
	Matrix matrix;
	
	//计算矩阵相加
	for (int i = 0; i < 2; i++)
		for (int j = 0; j < 3; j++)
			matrix.juzhen[i][j] = a.juzhen[i][j] + b.juzhen[i][j];	//矩阵相加

	return matrix;//返回相加后的对象
}

int main()
{
	//定义矩阵
	int a1[2][3] = { { 1, 2, 3 },
					 { 4, 5, 6 } };

	int a2[2][3] = { { 7, 8, 9 },
					 { 10, 11, 12 } };


	//实例化两个矩阵对象
	Matrix c1(a1);
	Matrix c2(a2);

	//使用重载的 +  号 进行两个矩阵的相加
	Matrix c3 = c1 + c2;
	
	//打印结果
	c3.print();

	return 0;
}

2.5 普通函数运算符重载

关键字:operator

格式:

函数返回值类型   operator   重载的运算符   ([参数列表]);//运算符重载,可以将operator和重载的运算符看成是函数名

例如:
	void    operator   +   (int  b,int c);  //重点:参数个数要与运算符需求的参数个数匹配

2.5.1 例

//普通函数运算符重载
//计算复数相加
class Complex {
public:
    Complex(int r, int i) : real(r), imag(i) {//构造函数
    
    }

    // 声明友元函数
    friend Complex operator+(const Complex& c1, const Complex& c2);

    void display(){
        cout << "复数:" << real << " + " << imag << "i" << endl;
    }

private:
    int real;//实数
    int imag;//虚数
};

// 在类外定义 + 运算符的重载
Complex operator+(const Complex& c1, const Complex& c2) {

    // 创建一个新的Complex对象,存储两个复数相加的结果
    Complex comp(c1.real + c2.real, c1.imag + c2.imag);
    return comp;
}

int main() {

    //实例化两个对象
    Complex c1(2, 3);
    Complex c2(1, -1);

    // 使用重载的 + 运算符
    Complex sum = c1 + c2;

    // 显示结果
    sum.display();

    return 0;
}

  • 29
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值