栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

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

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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(numerator) / denominator;
    }

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

上述程序的说明:

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

如果没有在类中定义转换函数,那么上述代码会报错,在定义了转换函数之后,f2会转换为double类型的0.6和4相加等到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(numerator) / denominator;
    }
    Fraction operator+(const Fraction& f) {  
	   //do plus (加的动作这里没有详细设计)
       ...
	   return f; 
	} 

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

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

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

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

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

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

说明:

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

0x05 explicit keyword

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

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

    operator double() const {
        return static_cast(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.6和4相加之后得到4.6,同样因为构造函数有explicit修饰,所以4.6不能再自动转换为Fraction。

所以会报错。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/976500.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号