对于类型转换函数(convert function),共有两种形式:
- 当前类转换成其他类
- 其他类转换成当前类
当前类转换成其他类
语法:
operator <typename>() const {...}
语法特点:
- 没有返回值
- 没有参数
- 不改变类的数据成员(const),因为是转换。
class Fraction{
public:
//non-explicit-one-argument ctor 可以把int类型转换成该类类型实例
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
//转换函数,可以转成double
operator double() const {
return (double) (m_numerator / m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; // 分母
};
//调用
Fraction f(3,5);
double d=4+f; // 编译器首先会找全局的函数operator +(int, Fraction)->没有
// 编译器再找有没有可以把Fraction 转换成double的转换函数
// operator double() ->有
其他类转换成当前类(non-explicit-one-argument ctor 非明确的单实参构造函数)
把其他类转换成当前类,需要使用non-explicit-one-argument ctor(非明确的单实参构造)函数来配合实现。
语法特点:
- non-explicit
- 实参只有一个(形参可以多个)的构造函数
- 一个引导转换的操作符重载函数
例如:
class Fraction{
public:
//non-explicit-one-argument ctor 可以把int类型转换成该类类型实例
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
//重载+操作符
Fraction operator +(const Fraction & f) {
return Fraction(......);//根据分数加法规则构造临时的Fraction变量并传值的方式返回
}
private:
int m_numerator; //分子
int m_denominator; // 分母
};
//调用
Fraction f(3,5);
double d=f+4; // 编译器首先会找全局的函数operator +(Fraction,int)->没有
//编译器再去Fraction的类内部找 operator+(int)的操作符重载函数->没有
// 编译器再找有没有可以把int转换成Fraction的转换函数->
//发现了non-explicit-one-argument ctor可以把int 转换成Fraction->
//然后再调用operator +(Fraction&) ->有
转换函数 vs non-explicit-one-argument ctor
如果以上两种方式同时存在,即Fraction即可以转换成double, 同时又支持int型数据转换成Fraction形式,则:
class Fraction{
public:
//non-explicit-one-argument ctor 可以把int类型转换成该类类型实例
Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
//转换函数,可以转成double
operator double() const {
return (double) (m_numerator / m_denominator);
}
//重载+操作符
Fraction operator +(const Fraction & f) {
return Fraction(f.m_numerator, m_denominator);//根据分数加法规则构造临时的Fraction变量
//并传值的方式返回
}
private:
int m_numerator; //分子
int m_denominator; // 分母
};
//调用
Fraction f(3,5);
Fraction f2 = f + 4;//错误 ->冲突,既可以把f转换成double,又可以把4转换成Fraction
double d = 4 + f;//正确
Paste_Image.png
explicit-one-argument ctor
对于上面类型转换的冲突,如果把构造函数前面加上explict关键字,就不会再有冲突。
因为explict常用语构造函数,表示必须显示调用构造函数才可以转换,即上面的例子,4不可以默认成Franction(4),如果需要转换必须明确调用才会发生转换。
class Fraction{
public:
//explicit-one-argument ctor 不可以把int类型转换成该类类型实例
explict Fraction(int num, int den = 1) : m_numerator(num), m_denominator(den) { }
//转换函数,可以转成double
operator double() const {
return (double) (m_numerator / m_denominator);
}
//重载+操作符
Fraction operator +(const Fraction & f) {
return Fraction(f.m_numerator, m_denominator);//根据分数加法规则构造临时的Fraction变量
//并传值的方式返回
}
private:
int m_numerator; //分子
int m_denominator; // 分母
};
//调用
Fraction f(3,5);
Fraction f2 = f + 4;//正确 ->不会把4转换成Fraction(4),只会把f转换成double
double d = 4 + f;//正确
explicit关键字,一般就用于约束构造函数上(不可以隐式转换)
网友评论