C++中对于用户自定义类对象的运算,要进行重载操作。如
class overload{
public:
...
private:
int num;
};
overload o1, o2;
int num;
//要实现的加法操作如下:
/*1*/overload o3 = o1 + o2;
/*2*/overload o4 = o1 + (任意int型);
/*3*/overload o5 = (任意int型) + o2;
/*4*/num = (任意int型) + o2;
/*5*/num = o1 + o2;
//以及一些其他的组合,原理一致,此处不列出
首先要为类定义构造函数:
overload():num(0) {}
overload(int a):num(a) {}
对于1、2式,直接进行运算符的重载就行。系统会将o1+o2变为o1.operator+(o2)的形式。为了保持类的封装性,最好是重载为成员函数。
//此重载可以兼容1、2式
//对于2式中的int型整数,会通过一个隐式转换(构造函数中的overload(int a):num(a) {}),变为overload类型的对象,然后执行加操作
overload operator+(const overload &o){
return overload(num + o.num);
}
//上式多一步隐式转换,性能就会受到影响,所以可以采用专门的重载函数
overload operator+(const int x){
return overload(num + x);
}
PS:上述两个重载返回值写的都是构造函数类型,原因在于如果写的是以下结构
overload res(num + x);
return res;
将会多出一个隐式的构造和析构过程(局部变量的拷贝引起),而直接返回构造函数,可以使此步骤发生在要赋值的类对象的内存空间中,减少构造和析构的过程。这叫做返回值优化(return value optimization)。
对于3式,由于无法产生a.operator+(overator &)的类型,所以需要重载为友元函数,但是影响了一定的封装性(因为类要求private的成员不可被外部访问,只可以被内部访问,而友元函数不属于内部的函数)。
//友元函数
//第一个友元函数多一步隐式转换,第二、三不会有隐式转换,原理一致,写哪个都可以
friend overload operator+(const overload &o1, const overload &o2){
return overload(o1.num + o2.num);
}
friend overload operator+(const int a, const overload &o2){
return overload(o1.num + a);
}
friend overload operator+(const overload &o1, const int a){
return overload(o1.num + a);
}
但是如果这还不能满足我们呢?如果我们要求类也可以转换为int型的数据呢?(4,5式)
这就要用到类型转换函数了。
类型转换函数形式如下:
operator 类型名( )
{
实现转换的语句;
}
在函数名前面不能指定函数类型,函数没有参数。其返回值的类型是由函数名中指定的类型名来确定的。类型转换函数只能作为成员函数,因为转换的主体是本类的对象。不能作为友元函数或普通函数。
从函数形式可以看到,它与运算符重载函数相似,都是用关键字operator开头,只是被重载的是类型名。int类型经过重载后,除了原有的含义外,还获得新的含义(将一个overload类对象转换为int类型数据,并指定了转换方法)。这样,编译系统不仅能识别原有的int型数据,而且还会把overload类对象作为int型数据处理。
本例的类型转换函数如下:
operator int(){
return num;
}
这个类型转换函数可以直接代替上述重载函数的功能,实现1,2,3,4,5式。
//o1,o2都转换为int类型的数据,进行相加后,再通过隐式转换,构造o3
overload o3 = o1 + o2;
overload o4 = o1 + (任意int型);
//没有int+overload类型的加法,但是系统会自动将o2变为int类型,执行加法后再构造o5
overload o5 = (任意int型) + o2;
num = (任意int型) + o2;
//o1,o2的结果转换为int
num = o1 + o2;
类型转换运算符的功能:当需要的时候,编译系统会自动调用这些函数,建立一个无名的临时对象(或临时变量)。
但是当类中同时出现以上函数时,会出现二义性,程序无法判定使用哪一种转换方法,所以需要自行选择合适的方法。
实验部分代码如下:
#include <iostream>
using namespace std;
class overload
{
public:
overload():num(0) {}
overload(int a):num(a) {}
#if 1
overload operator+(const overload &o){
return overload(num + o.num);
}
#endif
#if 0
//类型转换函数
operator int(){return num;}
#endif
//友元函数
friend ostream &operator<<(ostream &out, const overload &o){
return out << o.num;
}
#if 1
friend overload operator+(const overload &o1, const overload &o2){
return overload(o1.num + o2.num);
}
#endif
private:
int num;
};
int main()
{
overload o1(3);
overload o2(4);
overload o3 = o1 + o2;
cout << o3 << endl;
overload o4 = o1 + 5;
cout << o4 << endl;
overload o5 = 6 + o1;
cout << o5 << endl;
//int n1 = o1 + o2;
//cout << n1 << endl;
return 0;
}
参考文章:类型转换函数