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

标签 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() 运算符显式来解决,但我是在寻求解释而不是解决方案。

最佳答案

A可以从 int 构建或 const A& , B可以转换为这两个,因此这些表达式是有歧义的,因为编译器无法知道这两个不同的路径是否创建了一些A。来自B导致相同的结果。

这是由于 static_cast确定可能的转化路径的方法:

If a temporary object of type new_type can be declared and initialized with expression, as by new_type Temp(expression);, which may involve implicit conversions, a call to the constructor of new_type or a call to a user-defined conversion operator, then static_cast<type>(expression) computes and returns the value of that temporary object. (ref)

注意这部分:

which may involve implicit conversions, a call to the constructor of new_type or a call to a user-defined conversion operator

你可以隐式转换Bint , 然后构造 A来自 int .

或者您可以转换 BA根据转换运算符。

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

我建议构造函数 ( A(int) ) explicit ,而不是运营商。这通常是想要的行为。这将导致 static_cast<A>(b) 的明确行为: operator A()被使用。

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

关于c++ - 使用构造函数代替或类型转换运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26240357/

相关文章:

c# - 使用 LINQ 将 List<U> 转换为 List<T>

c++ - 函数重载,唯一变化是 "uint32_t"& uint64_t"在 c++ 的纯虚函数中

c# - 不能将 int 转换为 T,其中 T 是 bool。有没有办法用 C# 做到这一点?

c# - 为什么 "as"运算符在 C# 中不使用隐式转换运算符?

c++ - 在 C++ 中自定义日期格式

c++ - 嵌套在函数中的函数声明的命名空间

java - 检查有效的重载

c++ - 派生类中的重载方法与多重分派(dispatch)

c++ - 使用 GetComputerObjectName 启用哪些访问权限?

C++骰子程序难点