【c++】conversion function&explicit 转换函数和显式关键字

conversion function转换函数

语法

class Fraction {

public:
    Fraction(int num, int den = 1) : m_son(num), m_mom(den) {}
    // 必须加const
    // 返回类型为double
    // 函数参数this
    operator double const() {
        return (double) (double(m_son) / double(m_mom));
    }
private:
    int m_son;
    int m_mom;
};

函数调用

	Fraction f (3,5);
	// 若没有转换函数,此语句报错 有转换函数,编译器调用转换函数将f转换为double
	// 然后编译器继续使用operator(double,int)完成此语句	
	double b = f + 4; 

explicit 显式关键字

without explicit

不使用explicit时,当operator+操作符查询到只有(const FractionExplicit&f)重载类型时,会自动调用单实参构造函数来进行隐式转换
class FractionExplicit {

public:
    /**
     * non-explicit-one-argument ctor 非显性单实参构造函数
     * two parameter one argument
     * FractionExplicit d2 = f + 4; // call non-explicit ctor 将4转为 FractionNonExplicit(4,1)
     */
     FractionExplicit(int num, int den = 1) : m_son(num), m_mom(den) {}

    FractionExplicit operator+(const FractionExplicit &f) {
        return FractionExplicit(f.m_son * m_mom + f.m_mom * m_son, f.m_mom * m_mom);
    }

    int son() const {
        return m_son;
    }

    int mom() const {
        return m_mom;
    }

private:
    int m_son;
    int m_mom;
};

FractionExplicit f(3, 5);
// call non-explicit ctor 将4转为 FractionNonExplicit(4,1)
FractionExplicit d2 = f + 4; 

with explicit

class FractionExplicit {

public:
    /**
     *
     * explicit function
     * 加上explicit,编译器不会自动转换
     */
    explicit FractionExplicit(int num, int den = 1) : m_son(num), m_mom(den) {

    }

    FractionExplicit operator+(const FractionExplicit &f) {
        return FractionExplicit(f.m_son * m_mom + f.m_mom * m_son, f.m_mom * m_mom);
    }

    int son() const {
        return m_son;
    }

    int mom() const {
        return m_mom;
    }

private:
    int m_son;
    int m_mom;
};
FractionExplicit f(3, 5);
// 报错:Invalid operands to binary expression ('FractionExplicit' and 'int')
FractionExplicit d2 = f + 4; 
// 对整型进行显式转换
FractionExplicit d2 = f + FractionExplicit(4); 

常见错误

隐式转换和非显式构造函数导致产生二义性

class FractionExplicit {

public:
    /**
     * non-explicit-one-argument ctor 非显性单实参构造函数
     * two parameter one argument
     * FractionExplicit d2 = f + 4; // call non-explicit ctor 将4转为 FractionNonExplicit(4,1)
     */
     FractionExplicit(int num, int den = 1) : m_son(num), m_mom(den) {

    }

    // 必须加const
    // 返回类型为double
    // 函数参数this
    operator double const() {
        return (double) (double(m_son) / double(m_mom));
    }

    FractionExplicit operator+(const FractionExplicit &f) {
        return FractionExplicit(f.m_son * m_mom + f.m_mom * m_son, f.m_mom * m_mom);
    }

    int son() const {
        return m_son;
    }

    int mom() const {
        return m_mom;
    }

private:
    int m_son;
    int m_mom;
};

FractionExplicit f(3, 5);
// 报错:Use of overloaded operator '+' is ambiguous (with operand types 'FractionExplicit' and 'int')
// 因为操作符重载operator+(const FractionExplicit &f),所以编译器可以执行FractionExplicit(4),再执行加法
// 同时因为该类包含一个隐式转换函数,所以operator+也可以先double(f)然后重载为operator+(double,int)
// 因此编译器会报错,此处产生二义性
FractionExplicit d2 = f + 4;
// explicit FractionExplicit(int num, int den = 1) : m_son(num), m_mom(den) {}
// 此时仍然报错,此时编译器选择operator+(double,int),返回类型为double,不符合
FractionExplicit d2 = f + 4;
// 正确
FractionExplicit d2 = f + FractionExplicit(4);

多隐式转换造成的二义性

class Fraction {

public:
    Fraction(int num, int den = 1) : m_son(num), m_mom(den) {}

    // 必须加const
    // 返回类型为double
    // 函数参数this
    operator double const() {
        return (double) (double(m_son) / double(m_mom));
    }

    operator float const() {
        return (float) (float (m_son) / float (m_mom));
    }

private:
    int m_son;
    int m_mom;
};
Fraction f(3,5);
//  不能写成下面这种情形,因为有多个转换函数double() float(),而operator+对float double都有相应的操作符重载 所以需要显示转换f
// 报错:Use of overloaded operator '+' is ambiguous
float a = 4 + f;
// 4.6f
float a = 4 + double (f);
// 4.6f
float b = 4 + float (f);
// double 4.5999999999999996
double c = 4 + double (f);
// float(f)时会丢失部分精度,导致4.6 = 4.5999999999999996 d = 4.5999999046325684
double d = 4 + float (f);
posted @ 2021-02-23 16:34  kudo_shini  阅读(114)  评论(0编辑  收藏  举报