编写高质量代码:改善C++程序的150个建议(连载9)

发表于:2012-4-13 09:38

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:李健    来源:51Testing软件测试网采编

  在上面的代码中,调用DoSomething()函数时会发现实参与形参类型不一致,但是因为类A的构造函数只含有一个int类型的参数,所以编译器会以20为参数调用A的构造函数,以便构造临时对象,然后传给DoSomething()函数。不要为此而感到惊讶,其实编译器比想像的还要聪明:当无法完成直接隐式转换的时候,它不会罢休,它会尝试使用间接的方式。所以,下面的代码也是可以被编译器接受的:

  1. void DoSomething(A aObject);  
  2. float fval = 20.0f;  
  3. DoSomething(fval);

  这是一个多么奇妙的世界。这样的隐式转换在某些时候会变得相当微妙,一个误用也许会引起难以捉摸的错误。另外,由于在隐式转换过程中需要调用类的构造函数、析构函数,如果这种转换代价很大,那么这样的隐式转换将会影响系统性能。

  当然,我们熟知的隐式转换还包括“子类到基类的隐式转换”和“const到non-const的同类型隐式转换”。不过这两种转换是比较安全的,所以在这里就不再详细讨论。

  如果试图禁止所有的隐式类型转换,那么为了维持函数使用代码的简洁性,函数必须对所有的类型执行重载。这将是一个十分庞大且毫无技术含量的重复性工程,这不仅大大增加了函数实现的负担,重复的代码也严重偏离了DRY原则。

  说明 DRY— Don抰 Repeat Yourself Principle,直译为“不要重复自己”。简而言之,就是不要写重复的代码。DRY利用的方法就是抽象:把共同的事物抽象出来,把代码抽取到一个地方去,这样就可以避免重复写代码。

  C/C++对于这个问题采取的策略是“把问题交给程序员全权处理”。程序员既然享受了隐式变换所带来的便利,那么如果出现错误也是程序员需要负责的问题。权利与义务对等,这也算得上合情合理。但在程序员的眼里,这样的处理方式却不能让他们满意。后来C++设计者意识到了这个问题,于是提供了控制隐式转换的两条有效途径:

  使用具名转换函数

  来看一段代码:

  1. class Rational  
  2. {  
  3. public:  
  4.     Rational(int numerator = 0, int denominator = 1)  
  5.         :m_num(numerator),m_den(denominator){}  
  6.  
  7.     operator double() const  
  8.     {  
  9.    return ((double)m_num/(double)m_den);  
  10.     }  
  11. private:  
  12.      int m_num;  
  13.      int m_den;  
  14. };  
  15.  
  16. Rational r(1,2);  
  17. cout<<r<<endl;

  上面代码的本意是打印类似n/m的形式,可是结果输出的却是0.5。问题出现在哪里?当调用operator<<时,编译器会发现没有合适的函数存在,所以它就试图找到一个合适的隐式类型转换顺序,以使函数得到正常调用。本来程序中并不存在将Rational转为其他类型的转换规则,但是Rational::operator double函数告诉编译器Rational类型可以转换为double类型,所以就有了上述结果的出现。为了避免此类问题的出现,建议使用非C/C++关键字的具名函数,代码如下所示:

  1. class Rational  
  2. {  
  3. public:  
  4.      Rational(int numerator = 0, int denominator = 1);  
  5.      operator as_double() const;  
  6. private:  
  7.      int m_num;  
  8.      int m_den;  
  9. };  
  10.  
  11. Rational r(1,2);  
  12. cout<<r<<endl; // 提示无operator<<Rational重载函数

  使用 explicit 限制的构造函数

42/4<1234>
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号