1. 转换函数(Conversion function)
把类转换为基本数据类型的方法
#include <iostream>
using namespace std;
class Fraction{
public:
Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den){}
//把Fraction转为double
operator double() const {
return (double)m_numerator / m_denominator;
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
void test01(){
Fraction f(6, 5);
double d = 4 + f;
cout << d << endl;
}
int main(int argc, char *argv[]){
test01();
return 0;
}
关注类中的这个函数:
operator double() const {
return (double)m_numerator / m_denominator;
}
注意到函数没有返回值, 因为编译器知道返回值, 为了防止你多写了反而出错, 因此不要你写了.
当
void test01(){
Fraction f(6, 5);
double d = 4 + f;
cout << d << endl;
}
执行时, double d = 4 + f
, 编译器会先去寻找有没有重载+
运算符, 当没有找到, 便找有没有conversion function
, 找到了之后, 把f
转换为double
类型.
2. 传一个参数就够的非explicit构造函数隐式转换(non-explicit-one-argument ctor)
这个也是转换, 但是和1中的不同:
class Fraction{
public:
Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den){}
Fraction operator+(const Fraction& f){
return Fraction(m_numerator + f.m_numerator, m_denominator + f.m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
void test01(){
Fraction f(3, 5);
Fraction d2 = f + 4; //调用non-explicit ctor 将 4 转为 Fraction(4, 1)
//然后调用operator+
}
主要是删除了operator double() const;
函数, 增加了+
重载.
当执行d2 = f + 4
时, 编译器去找+
重载, 但是发现参数是const Fraction&
类型的, 与4
不符, 于是会发生隐式转换, 也就是调用non-explicit ctor 将 4 转为 Fraction(4, 1), 然后调用+
.
这里需要注意的是, 构造函数只能是一个参数, 一个是意思是传入一个就够了, 可以有默认参数.
3. 如果1 和 2 结合起来
代码如下:
class Fraction{
public:
Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den){}
operator double() const {
return (double)m_numerator / m_denominator;
}
Fraction operator+(const Fraction& f){
return Fraction(m_numerator + f.m_numerator, m_denominator + f.m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
void test01(){
Fraction f(3, 5);
Fraction d2 = f + 4;
}
这样子的话编译就会出错:
non_explicit_one_argument_ctor.cpp: In function ‘void test01()’:
non_explicit_one_argument_ctor.cpp:28:21: error: ambiguous overload for ‘operator+’ (operand types are ‘Fraction’ and ‘int’)
Fraction d2 = f + 4;
~~^~~
non_explicit_one_argument_ctor.cpp:28:21: note: candidate: operator+(double, int) <built-in>
non_explicit_one_argument_ctor.cpp:18:14: note: candidate: Fraction Fraction::operator+(const Fraction&)
Fraction operator+(const Fraction& f){
^~~~~~~~
这是因为
Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den){}
operator double() const {
return (double)m_numerator / m_denominator;
}
产生了冲突.
语句d2 = f + 4
, 编译器会不知道选取哪个方向, 因为它可以选取把4
隐式转换为Fraction
类型, 同样f
也可以转换为double
类型, 最后+
就不知道是调用基本数据类型的+
还是我们类中重载的+
了.
4. 如果加了explicit
代码:
class Fraction{
public:
explicit Fraction(int num, int den = 1)
: m_numerator(num), m_denominator(den){}
operator double() const {
return (double)m_numerator / m_denominator;
}
Fraction operator+(const Fraction& f){
return Fraction(m_numerator + f.m_numerator, m_denominator + f.m_denominator);
}
private:
int m_numerator; //分子
int m_denominator; //分母
};
void test01(){
Fraction f(3, 5);
Fraction d2 = f + 4; //调用non-explicit ctor 将 4 转为 Fraction(4, 1)
//然后调用operator+
}
在构造函数中加了explicit, 编译时的错误变了:
non_explicit_one_argument_ctor.cpp: In function ‘void test01()’:
non_explicit_one_argument_ctor.cpp:28:21: error: conversion from ‘double’ to non-scalar type ‘Fraction’ requested
Fraction d2 = f + 4; //调用non-explicit ctor 将 4 转为 Fraction(4, 1)
~~^~~
意思就是, d2 = f + 4
时, 4
是不能隐式转换了, 于是f
转为double
, 两者相加, 为double
, 然后因为d2
的类型是Fraction
, 所以要进行隐式转换, 但是不允许, 所以发生错误.
当d2
的类型改为double
时, 代码编译运行通过.