使用构造函数代替或类型转换运算符

时间:2014-10-07 16:02:45

标签: c++ casting overloading

我有以下代码

    class A {
    private:
            int n;

    public:
            A(int n) : n{n} {}
            A(const A & a) : n{a.n} {}
    };

    class B {
    private:
            int m;
    public:
            B(int n) : m{n} {}
            operator A() const { return A(m); }
            operator int() const { return m; }

    };

    int main(int, char**)
    {
            B b{1};

            (A)b;                // Fails
            static_cast<A>(b);   // Fails
            b.operator A();      // OK
    }

失败
call of overloaded ‘A(B&)’ is ambiguous

(gcc,但VC ++和clang似乎以同样的方式处理它)

我认为这三者都是完全相同的。使用B的运算符A()进行转换。显然,这不是正在发生的事情。为什么呢?

通过使int()运算符显式化可以很容易地解决问题,但我解释的不是解决方案。

1 个答案:

答案 0 :(得分:4)

A可以从intconst A&构造,B可以转换为这两者,因此这些表达式是不明确的,因为编译器无法知道是否从A创建一些B导致相同结果的两种不同途径。

这是由于static_cast确定可能的转换路径的方式:

  

如果可以使用表达式声明和初始化类型为new_type的临时对象,如new_type Temp(expression);,可能涉及隐式转换,则调用new_type的构造函数或调用对于用户定义的转换运算符,然后static_cast<type>(expression)计算并返回该临时对象的值。 (ref

请注意这一部分:

  

可能涉及隐式转换,对new_type的构造函数的调用或对用户定义的转换运算符的调用

您可以将B隐式转换为int,然后从A构建int

或者您可以根据转换运算符将B转换为A

这就是在这里使用C风格或static_cast时产生歧义的地方。

我建议制作构造函数(A(int)explicit,而不是运算符。这通常是想要的行为。这会导致static_cast<A>(b)的行为不明原因:operator A()被使用。

请注意,A a = b;是明确的:它将使用operator A(),因为隐式转化更喜欢用户定义的转化(ref