C++ Conversion Function(转换函数) and Explicit Keyword

C++ Conversion Function(转换函数) and Explicit Keyword


0x01 Conversion Function

转换函数的目的就是将一个类的对象转换为另一种类型,比如说在数学的角度,一个分数可以转换为一个小数;那么从程序的角度来说,一个分数类(Fraction)的对象也可以转换为浮点数(double),此时就需要用到Conversion Fraction.

Fraction类的代码如下:

class Fraction
{
public:
    Fraction(int num, int den = 1)
            : numerator(num), denominator(den) {}

    operator double() const {
        return static_cast<double>(numerator) / denominator;
    }

private:
    int numerator;    // 分子
    int denominator;  // 分母
};

上述程序的说明:

  • 需要注意的是构造函数有两个形参,但最后一个形参有默认值,所以在定义对象的时候,可以只给一个参数,也可以给两个参数:
Fraction f1(5); // 正确 分字为5,分母为默认值1
Fraction f2(3, 5); // 正确 分字为3,分母为5
  • 其中的operator double() const{···}就是转换函数,将Fraction对象转换为double,例如:
double d = f2 + 4;  // 4.6

如果没有在类中定义转换函数,那么上述代码会报错,在定义了转换函数之后,f2会转换为double类型的0.64相加等到4.6后赋值给变量d.

0x02 自动类型转换 (non-explicit ctor)

上面我们探讨了Fraction转换为double,其实反过来也是可以的,假设类的定义是下面这样的:

class Fraction
{
public:
    Fraction(int num, int den = 1)
            : numerator(num), denominator(den) {}
    Fraction operator+(const Fraction& f) {  
	   //do plus (加的动作这里没有详细设计)
       ...
	   return f; 
	} 

private:
    int numerator;    // 分子
    int denominator;  // 分母
};

有如下的对象:

Fraction f(3, 5);
Fraction f2 = f + 4; // 首先调用(non-explicit)构造函数将4转换为Fraction
					 // 再调用operator+

此时就将4转换为了Fraction.

0x03 Conversion Function与non-explicit ctor共存时

假设当前类的定义为:

class Fraction
{
public:
    Fraction(int num, int den = 1)
            : numerator(num), denominator(den) {}

    operator double() const {
        return static_cast<double>(numerator) / denominator;
    }
    Fraction operator+(const Fraction& f) {  
	   //do plus (加的动作这里没有详细设计)
       ...
	   return f; 
	} 

private:
    int numerator;    // 分子
    int denominator;  // 分母
};

Conversion Functionnon-explicit ctor共存,此时下面的代码会产生歧义:

Fraction f(3, 5);
Fraction f2 = f + 4; // Error: ambiguous

因为对于代码Fraction f2 = f + 4;会有两条可选路径:

  • 第一种情况是将4转换为Fraction,再调用operator+;
  • 第二种情况是f转换为double类型的0.6,再将0.64相加之后得到4.6,再调用non-explicit ctor转换为Fraction.

因为上述两种情况并不存在谁优于谁的情况,所以编译器也不知道调用哪个,所以会报错。

说明:

这里产生二义性并不是因为Conversion Functionnon-explicit ctor共存的原因,其产生的原因主要还是我们类的设计。

0x04 explicit keyword

当不允许发生隐式类型转换时,应该明确拒绝,即在构造函数之前加上 explicit关键字:

class Fraction
{
public:
    explicit Fraction(int num, int den = 1)
            : numerator(num), denominator(den) {}

    operator double() const {
        return static_cast<double>(numerator) / denominator;
    }
    Fraction operator+(const Fraction& f) {  
	   //do plus (加的动作这里没有详细设计)
       ...
	   return f; 
	} 

private:
    int numerator;    // 分子
    int denominator;  // 分母
};

但是下面的代码依旧会出现问题,但是不再是二义性的问题了:

Fraction f(3, 5);
Fraction f2 = f + 4; // Error: conversion from 'double' to non-scalar type       						'Fraction' requested 

此时0x03中的两种路径都行不通了:

  • 因为构造函数有explicit修饰,所以4不能再自动转换为Fraction
  • 虽然能够将f转换为double类型的0.6,再将0.64相加之后得到4.6,同样因为构造函数有explicit修饰,所以4.6不能再自动转换为Fraction

所以会报错。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值