Item5 谨慎定义类型转换函数

        C++编译器能够在两种数据类型之间进行隐式转换(implicit conversions),它继承了 C 语言的转换方法,例如允许把 char 隐式转换为 int 和从 short 隐式转换为 double。因此当你把一个 short 值传递给准备接受 double 参数值的函数时,依然可以成功运行。C 中许多这种可怕的转换可能会导致数据的丢失,它们在 C++中依然存在,包括 int 到 short 的转换和 double 到 char 的转换。
        你对这些类型转换是无能为力的,因为它们是语言本身的特性。不过当你增加自己的类型时,你就可以有更多的控制力,因为你能选择是否提供函数让编译器进行隐式类型转换。有 两 种 函 数 允 许 编 译 器 进 行 这 些 的 转 换 : 单 参 数 构 造 函 数 ( single-argument constructors)和隐式类型转换运算符。单参数构造函数是指只用一个参数即可以调用的构造函数。该函数可以是只定义了一个参数,也可以是虽定义了多个参数但第一个参数以后的所有参数都有缺省值。以下有两个例子:
 

class CPerson{
private:
    string sName;
public://单参构造,隐式类型转换
    CPerson(string name) : sName(name){}
    void IntroduceOneself(){ cout << "Hello everyone ! My name is " << sName << " . " << endl; }
};

    CPerson oPerson = "Tony";
    oPerson.IntroduceOneself();

 


class CRational{//有理分数
private:
    int iNumerator;//分子
    int iDenominator;//分母
public:
    CRational(int numerator = 0, int denominator = 1) : iNumerator(numerator), iDenominator(denominator){}
    //隐式类型转换运算符
    operator double() const{ return (static_cast<double>(iNumerator) / static_cast<double>(iDenominator)); }
};

    CRational oRational(1,2);
    cout << "100 * " << oRational << " = " << 100 * oRational << endl;

 

假设你忘了为 Rational 对象定义 operator<<。你可能想打印操作将失败,因为没有合适的的 operator<<被调用。但是你错了。当编译器调用 operator<<时,会发现没有这样的函数存在,但是它会试图找到一个合适的隐式类型转换顺序以使得函数调用正常运行。类型转换顺序的规则定义是复杂的,但是在现在这种情况下,编译器会发现它们能调用CRational::operator double 函数来把 oRational 转换为 double 类型。所以上述代码打印的结果是一个浮点数,而不是一个有理数。这简直是一个灾难,但是它表明了隐式类型转换的缺点:它们的存在将导致错误的发生。

解决方法是用不使用语法关键字的等同的函数来替代转换运算符。例如为了把CRational 对象转换为 double,用 asDouble 函数代替 operator double 函数。在多数情况下,这种显式转换函数的使用虽然不方便,但是函数被悄悄调用的情况不再会发生,这点损失是值得的。一般来说,越有经验的 C++程序员就越喜欢避开类型转换运算符。例如在 C++标准库(参见 Effective C++条款 49 和 M35)委员会工作的人员是在此领域最有经验的, 他们加在库函数中的 string 类型没有包括隐式地从 string 转换成 C 风格的char*的功能,而是定义了一个成员函数 c_str 用来完成这个转换,这是巧合么?我看不是。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值