C++之运算符重载(一)

C++支持运算符重载。运算符重载的好处是使得使用类的人更加方便。设计类的人只不过是把设计函数变成了设计运算符重载。因此,运算符重载的本质仍旧是一个函数。

要想使用运算符重载,必须借助关键字operator。

C++对运算符重载是有限制的,其中:   .     ::      ?:       *       sizeof           这五个运算符是不能被重载的。

运算符重载并不能改变运算符的优先级和结合性。

运算符重载可以分为全局重载和成员函数重载;根据运算符的目数,可以分为单目运算符重载和双目运算符重载。

全局双目运算符重载

下面的代码将双目运算符重载为全局函数。

#include<iostream>

class MyComplex
{
private:
	double a;
	double b;
public:
	MyComplex(double x = 0.0,double y = 0.0);
	MyComplex(const MyComplex& C);
	double getImag()const;
	double getReal()const;
	void show()const;
};
#include "MyComplex.h"

MyComplex::MyComplex(double x, double y):a(x),b(y)
{
}

MyComplex::MyComplex(const MyComplex& C)
{
	this->a = C.a;
	this->b = C.b;
}

double MyComplex::getImag()const
{
	return this->b;
}

double MyComplex::getReal()const
{
	return this->a;
}

void MyComplex::show()const
{
	std::cout << a << "+" << b << "i" << std::endl;
}
#include"MyComplex.h"

MyComplex operator+(const MyComplex& c1, const MyComplex& c2);

int main()
{
	MyComplex c1(3.3, 2.4);
	MyComplex c2(2, 3);
	MyComplex c3 = c1 + c2;
	
	MyComplex c4 = operator+(c1, c2);			//运算符重载的本质就是函数

	c1.show();
	c2.show();
	c3.show();
	c4.show();

	return 0;
}

MyComplex operator+(const MyComplex& c1, const MyComplex& c2)
{
	//由于a,b是类的私有成员,因此可以这样解决无法访问a,b的问题。
	//让类提供一个获取a,b值的接口即可。
	MyComplex tmp(c1.getReal() + c2.getReal(), c1.getImag() + c2.getImag());
	return tmp;
}#include"MyComplex.h"

MyComplex operator+(const MyComplex& c1, const MyComplex& c2);

int main()
{
	MyComplex c1(3.3, 2.4);
	MyComplex c2(2, 3);
	MyComplex c3 = c1 + c2;
	
	MyComplex c4 = operator+(c1, c2);			//运算符重载的本质就是函数

	c1.show();
	c2.show();
	c3.show();
	c4.show();

	return 0;
}

MyComplex operator+(const MyComplex& c1, const MyComplex& c2)
{
	//由于a,b是类的私有成员,因此可以这样解决无法访问a,b的问题。
	//让类提供一个获取a,b值的接口即可。
	MyComplex tmp(c1.getReal() + c2.getReal(), c1.getImag() + c2.getImag());
	return tmp;
}

程序执行结果如下:

可以看到无论是直接使用+还是使用operator+函数来调用,都完成了c1和c2的相加工作。此次的运算符重载使用了类提供的接口获取私有成员的值。更一般的做法是将全局运算符重载声明为类的友元函数。如下:

#include<iostream>

class MyComplex
{
private:
	double a;
	double b;
	//声明友元函数
	friend MyComplex operator+(const MyComplex& c1, const MyComplex& c2);
public:
	MyComplex(double x = 0.0,double y = 0.0);
	MyComplex(const MyComplex& C);
	double getImag()const;
	double getReal()const;
	void show()const;
};

这样我们的运算符重载函数就可以访问类的私有成员了,可以改为如下:

MyComplex operator+(const MyComplex& c1, const MyComplex& c2)
{
	MyComplex tmp(c1.a + c2.a, c1.b + c2.b);
	return tmp;
}

这就是友元函数经常使用的地方。

成员函数双目运算符重载

#include<iostream>

class MyComplex
{
private:
	double a;
	double b;
	//声明友元函数
	//friend MyComplex operator+(const MyComplex& c1, const MyComplex& c2);
public:
	MyComplex(double x = 0.0,double y = 0.0);
	MyComplex(const MyComplex& C);
	double getImag()const;
	double getReal()const;
	void show()const;
	//做为成员函数重载运算符
	MyComplex operator+(const MyComplex& c);
};

MyComplex::MyComplex(double x, double y):a(x),b(y)
{
}

MyComplex::MyComplex(const MyComplex& C)
{
	this->a = C.a;
	this->b = C.b;
}

double MyComplex::getImag()const
{
	return this->b;
}

double MyComplex::getReal()const
{
	return this->a;
}

void MyComplex::show()const
{
	std::cout << a << "+" << b << "i" << std::endl;
}

MyComplex MyComplex::operator+(const MyComplex& c)
{
	MyComplex tmp(this->a + c.a, this->b + c.b);
	return tmp;
}
#include"MyComplex.h"

//MyComplex operator+(const MyComplex& c1, const MyComplex& c2);

int main()
{
	MyComplex c1(3.3, 2.4);
	MyComplex c2(2, 3);
	MyComplex c3 = c1 + c2;
	
	MyComplex c4 = c1.operator+(c2);			//运算符重载的本质就是函数

	c1.show();
	c2.show();
	c3.show();
	c4.show();

	return 0;
}

//全局双目运算符重载
//MyComplex operator+(const MyComplex& c1, const MyComplex& c2)
//{
//	//由于a,b是类的私有成员,因此可以这样解决无法访问a,b的问题。
//	//让类提供一个获取a,b值的接口即可。
//	//MyComplex tmp(c1.getReal() + c2.getReal(), c1.getImag() + c2.getImag());
//	//return tmp;
//	MyComplex tmp(c1.a + c2.a, c1.b + c2.b);
//	return tmp;
//}

运行结果如下:

作为成员函数重载运算符的时候,由于成员函数含有this指针。所以我们只传递一个参数就够了。

全局重载单目运算符(前置++)

单目运算符只有一个操作数。他的重载比较复杂。首先在类内声明友元函数。注意必须传递引用才能实现单目得效果。

friend MyComplex& operator++(MyComplex& c);

然后实现如下:

MyComplex& operator++(MyComplex& c)
{
//要保证先自增,再被使用
	c.a++;
	c.b++;
	return c;
}

成员函数单目运算符重载(前置++)

MyComplex& MyComplex::operator++()
{
	this->a++;
	this->b++;
	return *this;
}

全局重载单目运算符(后置++)

后置++得函数原型和前置++不一样,否则编译器将认为这是一个函数的重定义。出于这一点考虑,C++要求后置运算符重载含有一个占位参数。这个参数什么用都没有,只是为了让编译器确定这是后置运算符。

friend MyComplex operator++(MyComplex& c, int);
MyComplex operator++(MyComplex& c, int)
{
//返回的是值,不是引用。
	MyComplex tmp(c);
	c.a++;
	c.b++;
	return tmp;
}

成员函数单目运算符重载(后置++)

MyComplex MyComplex::operator++(int)
{
	MyComplex tmp(*this);
	this->a++;
	this->b++;
	return tmp;
}

下面给出所有的代码:

//头文件
#pragma once

#include<iostream>

class MyComplex
{
private:
	double a;
	double b;
	//声明友元函数
	//friend MyComplex operator+(const MyComplex& c1, const MyComplex& c2);
	//重载前置++
	//friend MyComplex& operator++(MyComplex& c);
	//重载后置++
	//friend MyComplex operator++(MyComplex& c, int);
public:
	MyComplex(double x = 0.0,double y = 0.0);
	MyComplex(const MyComplex& C);
	double getImag()const;
	double getReal()const;
	void show()const;
	//做为成员函数重载运算符
	MyComplex operator+(const MyComplex& c);
	//前置++重载
	MyComplex& operator++();
	//后置++重载
	MyComplex operator++(int);
};

 

//MyComplex.cpp
#include "MyComplex.h"

MyComplex::MyComplex(double x, double y):a(x),b(y)
{
}

MyComplex::MyComplex(const MyComplex& C)
{
	this->a = C.a;
	this->b = C.b;
}

double MyComplex::getImag()const
{
	return this->b;
}

double MyComplex::getReal()const
{
	return this->a;
}

void MyComplex::show()const
{
	std::cout << a << "+" << b << "i" << std::endl;
}

MyComplex MyComplex::operator+(const MyComplex& c)
{
	MyComplex tmp(this->a + c.a, this->b + c.b);
	return tmp;
}

MyComplex& MyComplex::operator++()
{
	this->a++;
	this->b++;
	return *this;
}

MyComplex MyComplex::operator++(int)
{
	MyComplex tmp(*this);
	this->a++;
	this->b++;
	return tmp;
}
//main.cpp

#include"MyComplex.h"

//MyComplex operator+(const MyComplex& c1, const MyComplex& c2);

//MyComplex& operator++(MyComplex& c);

//MyComplex operator++(MyComplex& c, int);

int main()
{
	MyComplex c1(3.3, 2.4);
	MyComplex c2(2, 3);
	MyComplex c3 = c1 + c2;
	
	MyComplex c4 = c1.operator+(c2);			//运算符重载的本质就是函数

	(++c2).show();
	c2++.show();

	//c1.show();
	//c2.show();
	//c3.show();
	//c4.show();

	return 0;
}

//全局双目运算符重载
//MyComplex operator+(const MyComplex& c1, const MyComplex& c2)
//{
//	//由于a,b是类的私有成员,因此可以这样解决无法访问a,b的问题。
//	//让类提供一个获取a,b值的接口即可。
//	//MyComplex tmp(c1.getReal() + c2.getReal(), c1.getImag() + c2.getImag());
//	//return tmp;
//	MyComplex tmp(c1.a + c2.a, c1.b + c2.b);
//	return tmp;
//}

//MyComplex& operator++(MyComplex& c)
//{
	////保证先自增,在使用。
//	c.a++;
//	c.b++;
//	return c;
//}

//MyComplex operator++(MyComplex& c, int)
//{
//	MyComplex tmp(c);
//	c.a++;
//	c.b++;
//	return tmp;
//}

 

发布了222 篇原创文章 · 获赞 174 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/zy010101/article/details/105240318