找回密码
 FreeOZ用户注册
查看: 1672|回复: 0
打印 上一主题 下一主题

[论坛技术] 再说C++的类型转换:隐式转换

[复制链接]
跳转到指定楼层
1#
发表于 11-5-2009 22:08:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?FreeOZ用户注册

x
在 Effictive C++ 第45条款中说:清楚知道C++译译器为我们完成和调用哪些函数。
这个主题是很好的,可惜里面说到的内容又是翻来覆去说copy constructor之类的东西。

我觉得C++编译器偷偷摸摸搞的小动作中,隐式转换是最可怕的。

先看下面的程序段:
  1. template<class T> class X { public: X(double x) {} };
  2. void foo(X<int> const & x) { cout << "foo" << endl; }

  3. int main() { foo(1.5); return 0; }
复制代码
事实上这个程序是可以成功编译并运行的。需要foo()并没有定义参数为double的函数,但因为X<T>包含了参数为double的构造函数,
所以上面的例子中,foo(1.5)的执行流程是:
1.5 -> X<int>临时对象 -> foo(X<int> const &)执行

注意,由于C++明确禁止把无名临时变量用做非const引用参数,所以,如果定义为:
  1. void foo(X<int> &x) { ... }
复制代码
由程序编译不成功。

对于要执行的任意函数foo(x),编译器会试图找到完全匹配的函数声明。如果找不到,编译器会试图通过在实参上进行隐式转换来找到合适
的函数
。上面的例子中,编译器没有找到foo(double)这样的函数定义,但找到了一个同名的函数foo(X<int> const&),而且能找到
double -> X的转换(通过X<T>::X(double)这个构造函数),于是就执行了隐式转换。

这种转换能带来方便,但同时也带来了问题。如果你另外有:
void foo(X<string> &x) { ... }

那么编译器就罢工了,因为会出现ambiguity,编译器不知道你想要哪一个。

反向隐式转换也是可能的:
  1. template<class T> class X {
  2. public:
  3.   operator double();
  4. };

  5. void foo(double v);

  6. int main() {
  7.   X x;
  8.   foo(x);
  9.   return 0;
  10. }
复制代码
这种情况下,x会隐式转换成double,然后再进行函数调用。考虑下面的情况:
  1. template<class T> class X {
  2. public:
  3.   operator double();
  4.   operator char *();
  5. };

  6. int main()
  7. {
  8.   cout << X << endl;
  9. }
复制代码
这种情况下编译器会因为ambiguous而罢工,因为他试图把X转成合适的类型时发现了double和char*两种类型,
结果不知所措了。

在可能的情况可,我们最好能把隐式转换显式化,也就是说,把变量变成最终的形式,而不是等待编译器也帮我们
转换。

隐式转换同样也影响着类的操作符重载。在通常情况下,我们在实现类的操作符重载时,可以选持成员函数和非成员
函数两种方式。如果选择为成员函数,则可以显式的禁止隐式转换。比如:
  1. template<class T> class X {
  2. public:
  3.   X(double d);
  4.   ~X();
  5.   X const & operator += (X const &);
  6. };

  7. template<class T> class Y {
  8. public:
  9.   Y(double d);
  10.   ~Y();
  11.   friend Y const & operator += (Y const &);
  12. }
复制代码
对于X<int> x; Y<int> y;double d = 1.0来说  d+= x; 是不成立的,而 d += y;则成立,但操作后左式的值没有改变,
显然,我们不希望有这种bug出现在程序中。但对于非赋值的二元操作符重载来说,我们一般希望对称的表达式,所以一般建议
是允许隐式转换,即不采用成员函数的方式来设定操作符重载。

参考:
* C++编译惯用法,2.4
回复  

使用道具 举报

您需要登录后才可以回帖 登录 | FreeOZ用户注册

本版积分规则

小黑屋|手机版|Archiver|FreeOZ论坛

GMT+10, 28-7-2026 03:26 , Processed in 0.010542 second(s), 17 queries , Gzip On, Redis On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表