转自:https://blog.csdn.net/hyman_c/article/details/52954445
我们知道在C++中可以通过重载运算符的方式,使类实现类似于基本类型的运算符操作,如+、-、*、/等等。本文介绍这种重载运算符的两种方法。
我们先自定义一个类,来作为本次研究的对象:
class Integer
{
public:
Integer(){}
Integer(int i):m_i(i){}
void get_val()
{
cout<<m_i<<endl;
}
private:
int m_i;
};
我们先看一下这个类,类中只包含一个私有的成员变量m_i,然后分别定义了无参和有参两种构造函数,并定义了一个函数get_val用于打印m_i的值来验证结果。
为了演示,我们分别重载运算符"+"和"-",通过运算符重载我们要实现的效果是:
-
Integet a,b;
-
Integer c= a + b;
-
c = a - b;
首先我们用第一种方法,通过成员函数的形式来实现运算符重载。最简单的重载形式如下:
-
Integer operator+(Integer that)
-
{
-
Integer i;
-
i.m_i=this->m_i+that.m_i;
-
return i;
-
}
我们在main函数中进行调用,发现已经达到了目的:
-
int main()
-
{
-
Integer a(10),b(20);
-
Integer c=a+b;
-
c.get_val();
-
return 0;
-
}
运行结果:
-
[Hyman@Hyman-PC Integer]$ g++ integer.cpp
-
[Hyman@Hyman-PC Integer]$ ./a.out
-
30
那么是不是这样就算重载成功了呢?
“当然不是!”
“是的话我还在这废什么话?”
这种重载函数虽然能够达到重载的效果,但是还存在三个隐患,作为一个追去完美的程序员,我们必须指出来:
1、参数采用Integer that,在运行时势必会利用Integer的拷贝构造函数构建参数副本,如果Integer定义的很大的话,造成了资源的不必要浪费,所以这里要改成引用的形式--Integer& that,但是仅仅利用引用还是不够的,因为如果b的类型是const Integer 呢?Integer c=a+b;就会编译出错,因为const 类型的引用,是不能传给非const类型的引用的,所以,上述操作符重载函数就应该改成这样:
-
Integer operator+(const Integer& that)
-
{
-
Integer i;
-
i.m_i=this->m_i+that.m_i;
-
return i;
-
}
2、如果a改成const Integer的形式,同样也无法调用,原因和第一条一样,Integer operator+(const Integer& that)中隐含包含的this指针不是const类型的,因此不能被const Integer类型的对象使用,这次把a改成const Integer,编译下,出现下面的错误:
-
[Hyman@Hyman-PC Integer]$ g++ integer.cpp
-
integer.cpp: In function ‘int main()’:
-
integer.cpp:28: 错误:将‘const Integer’作为‘Integer Integer::operator+(const Integer&)’的‘this’实参时丢弃了类型限定
怎么解决?当然是把this指针也申明成const类型,那么现在函数原型就变成下面这副鬼样子:
-
Integer operator+(const Integer& that) const
-
{
-
Integer i;
-
i.m_i=this->m_i+that.m_i;
-
return i;
-
}
3、最后一条,先问各位看官(如果有的话,没有就是我自言自语了),见过下面这种基本类型的加法运算吗:
(2+3)=4
可能有童鞋会说,这是什么玩意儿?解释一下,我的意思就是说,大家有见过把一个基本类型的对象赋值给一个+操作符返回的对象吗?
答案肯定是见过!
”在哪见得?“
”刚在这见得“。
但是我们自定义的这个类就支持这种操作,我们在main函数中这样调用:
-
int main()
-
{
-
const Integer a(10);
-
const Integer b(20);
-
Integer d(100);
-
Integer c=a+b;
-
(a+b)=d;
-
//c.get_val();
-
return 0;
-
}
然后我们进行编译,华丽丽的通过了:
-
[Hyman@Hyman-PC Integer]$ g++ integer.cpp
-
[Hyman@Hyman-PC Integer]$
这当然不可以,我们重载操作符的目的就是想让我们自己定义的类向基本类型一样符合我们对操作符操作的理解,而支持这样奇怪的运算方式,显然超出了我们的理解,所以这也要改!怎么改?很简单,在返回值前面也加一个const,这样整个+的重载函数就变成了这样:
-
const Integer operator+(const Integer& that) const
-
{
-
Integer i;
-
i.m_i=this->m_i+that.m_i;
-
return i;
-
}
现在还是编译上面main函数中的代码就会报错:
-
[Hyman@Hyman-PC Integer]$ g++ integer.cpp
-
integer.cpp: In function ‘int main()’:
-
integer.cpp:30: 错误:将‘const Integer’作为‘Integer& Integer::operator=(const Integer&)’的‘this’实参时丢弃了类型限定
但是这正是我们需要的。
这样,就完成了对+的重载,完美!!
好接下来,介绍下另外一种利用友元函数进行重载的方式,附上代码,不再多说,各位看官自己体会去吧:
-
const Integer operator-(const Integer& a,const Integer& b)
-
{
-
Integer i;
-
i.m_i=a.m_i-b.m_i;
-
return i;
-
}
最后附上整个文章的代码:
#include<iostream>
using namespace std;
class Integer
{
public:
Integer(){}
Integer(int i) :m_i(i){}
const Integer operator+(const Integer& that) const;
void get_val()
{
cout << m_i << endl;
}
private:
int m_i;
friend const Integer operator-(const Integer& a, const Integer& b);
};
const Integer Integer::operator+(const Integer& that) const
{
Integer i;
i.m_i = this->m_i + that.m_i;
return i;
}
const Integer operator-(const Integer& a, const Integer& b)
{
Integer i;
i.m_i = a.m_i - b.m_i;
return i;
}
int main()
{
const Integer a(10);
const Integer b(20);
Integer d(100);
Integer c = a + b;
d = a - b;
//(a+b)=d;
c.get_val();
d.get_val();
return 0;
}
后来看书看到的:
定义一个重载运算符就像定义一个函数,只是该函数的名字是operator@,这里@代表运算符。函数参数表中参数的个数取决于两个因素:
1.运算符是一元的(一个参数)还是二元的(两个参数)
2.运算符被定义为全局函数(对于一元运算符是一个参数,对于二元运算符是两个参数),如果运算符是成员函数(对于一元运算符没有参数,对于二元运算符是一个参数)