当心潜在的二义性

   在《Effective C++》中有一篇《当心潜在的二义性》。

 

  这是潜在二义性的一个例子:

  class B;                    // 对类B提前声明
                            //
class A {
public:
  A(const B&);              // 可以从B构造而来的类A
};

class B {
public:
  operator A() const;       // 可以从A转换而来的类B
};

这些类的声明没一点错——他们可以在相同的程序中共存而没一点问题。但是,看看下面,当把这两个类结合起来使用,在一个输入参数为A的函数里实际传进了一个B的对象,这时将会发生什么呢?

void f(const A&);

B b;

f(b);                       // 错误!——二义

一看到对f的调用,编译器就知道它必须产生一个类型A的对象,即使它手上拿着的是一个类型B的对象。有两种都很好的方法来实现(见条款M5)。一种方法是调用类A的构造函数,它以b为参数构造一个新的A的对象。另一种方法是调用类B里自定义的转换运算符,它将b转换成一个A的对象。因为这两个途径都一样可行,编译器拒绝从他们中选择一个。

 

但是我在g++下编了如下的程序:

class B;

class A
{
public:
 A(const B &b){cout << "B to A" << endl;}
 //A(const A &a);
};


class B
{
public:
 operator A()const{cout << "BB to A" << endl;}
};


void f(const A &a)
{
 cout << "f() in" << endl;
}


int main()
{
 B b = B();
 //A a = b;
 f(b);
 
}

居然能通过。输出为:

 

    看到这里, 就有点奇怪了。这么g++不产生歧义啊。

    我又修改了一下。如下:

   

  看出来了吗?就是把B::operator A()const 后面的const去掉了。结果是:

 很奇怪的结果。为什么呢?

对于第二种情况,我想应该是精确匹配起作用。因为b是一个非const的B,通过精确匹配掉用了B::operator A()。

对于第一种,我就有点像不明白了。A::A(const B &b)和B::operator A()const 就有同样的参数匹配等级。不知道。。。。。

 

带着这种疑惑,我把上面的程序用vs2008编译了一下,哈哈。。没通过,看了一下编译结果:

 应该就是解析时产生了歧义吧。

看来vs2008在这方面做的还是不错。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值