上一篇博文关于C++运算符重载的注意事项进行了整理(C++运算符重载使用注意事项),发现使用友元函数和成员函数定义运算符重载在使用过程中还是有一些局限性的,例如:
1、使用友元函数重载实现两种不同数据类型的运算,是不支持交换顺序的,故需要定义2个函数。
2、两种不同类型的数据类型进行不同简单运算时,需要针对不同的运算写不同的函数。
比如“对象+double”、“对象-double”,"对象*double"运算如果要支持结合律,则需要定义2*3个函数。但是转换构造函数则可以解决这个问题。而类型转换函数能实现把自定义对象转换为普通类型。
转换构造函数:
1、作用:用于把其他类型转换(普通数据类型或者其他)为自定义对象
2、书写格式:Complex (double r) { } //要求形参只能有一个参数
3、注意点:转换构造函数配合使用运算符重载函数实现操作数交换律,要求是运算符重载函
数是友元函数。
类型转换函数:
1、作用:把自定义对象转换为普通类型
2、书写格式:operator double() { return real; } //要求函数名称为要转换的类型且函数无形参
3、注意点:与类型转换函数具有二义性,使用过程中需要注意。
使用场景:转换构造函数可以实现 Complex对象+double=Complex对象 的运算,并支持顺序交换。
主要思想:隐式转换double类型为Complex对象,然后根据已有的运算符重载函数进行调用
class Complex {
private:
double real;
double imag;
public:
//通常用于实现不同数据类型赋值给类数据成员的应用,根据实际业务场景进行初始化对象
//因为此处实部本身就是double类型,这里其实就是调用只有一个参数的构造函数。
Complex (double r) {
real = r;
imag = 0;
}
Complex() {
real = 0;
imag = 0;
}
Complex(double r, double m) {
real = r;
imag = m;
}
double getReal();
double getImag();
void display();
Complex operator+(Complex& c1); //用作两个Complex对象相加
};
int main(){
Complex c1(3.6,2);
Complex c2;
double d2 = 2.1234;
c2 = c1 + d2; //正确
//编译系统发现右边是double类型,
// 1、先找是否有double与Complex的运算符重载,发现没有,只有Complex+Complex
// 2、再找转换构造函数,发现有double的转换构造函数,则把double自动转换为Complex对象
//c2 = d2 + c1; //错误,目前不支持顺序交换,下面进行介绍
}
注意点:
1)转换构造函数可以理解为灵活的构造函数,实际上也是创建对象初始化,
2)要求形参只能有一个参数
上面程序不支持交换的原因:未使用友元函数定义重载函数。使用成员函数重载默认第一个参数是Complex 对象,所以不支持。需改成友元函数实现重载则支持交换律。代码如下:
class Complex {
private:
double real;
double imag;
public:
//通常用于实现不同数据类型赋值给类数据成员的应用,根据实际业务场景进行初始化对象
//因为此处实部本身就是double类型,这里其实就是调用只有一个参数的构造函数。
Complex (double r) {
real = r;
imag = 0;
}
Complex() {
real = 0;
imag = 0;
}
Complex(double r, double m) {
real = r;
imag = m;
}
double getReal();
double getImag();
void display();
friend Complex operator+(Complex c1, Complex c2); //友元函数实现运算符重载
};
int main(){
Complex c1(3.6,2);
Complex c2;
Complex c3;
double d2 = 2.1234;
c2 = c1 + d2; //正确
c3 = d2 + c1; //正确
}
上面转换构造函数可以把double类型转换为Complex 对象。实现Complex +double=Complex 的运算,那如果要实现Complex +double=double呢? 就需要使用类型转换函数。主要思想是把Complex对象隐式转换成double对象。
class Complex {
private:
double real;
double imag;
public:
//通常用于实现不同数据类型赋值给类数据成员的应用,根据实际业务场景进行初始化对象
//因为此处实部本身就是double类型,这里其实就是调用只有一个参数的构造函数。
Complex (double r) {
real = r;
imag = 0;
}
//类型转换函数 类似于运算符重载的写法,1、要求函数名称为要转换的类型 2、函数无形参
operator double() {
return real;
}
Complex() {
real = 0;
imag = 0;
}
Complex(double r, double m) {
real = r;
imag = m;
}
double getReal();
double getImag();
void display();
//friend Complex operator+(Complex c1, Complex c2); //友元函数实现运算符重载
};
int main(){
Complex c1(3.6,2);
double d2 = 2.1234;
double d3;
d3 = c1 + d2; //正确
d3 = d2 + c1; //正确
}
注意点:
1)类型转换函数运算符重载的写法。a.函数名称为要转换的类型 b.函数无形参
2) 类型转换函数与运算符重载的二义性:
如果类中包含转换构造函数、运算符“+”的重载函数和类型转换函数。
那么当调用double+Complex时,系统不知道是把double转换为Complex,还是把 Complex转换为double。所以如果需要使用类型转换函数,就应去掉运算符重载函数。
转换构造函数:
1、作用:用于把其他类型转换(普通数据类型或者其他)为自定义对象
2、书写格式:Complex (double r) { } //要求形参只能有一个参数
3、注意点:转换构造函数配合使用运算符重载函数实现操作数交换律,要求是运算符重载函
数是友元函数。
类型转换函数:
1、作用:把自定义对象转换为普通类型
2、书写格式:operator double() { return real; } //要求函数名称为要转换的类型且函数无形参
3、注意点:与类型转换函数具有二义性,使用过程中需要注意。