(涉及显式)优先级与运算符和构造函数转换

时间:2015-12-31 10:22:00

标签: c++ type-conversion explicit

我浏览了很多与转换相关的问题,但似乎没有人以这种方式讨论显式关键字。 这是代码:

struct B;
struct A{
    /*explicit*/ A(const B&){ cout << 1; }  // *1
};
struct B{
    /*explicit*/ operator A()const{ cout << 2; } // *2
};

void foo(const A &){}

int main(void){
    B b;
    foo( /*static_cast<A>*/ (b) ); // *3
}

结果:(Y:未注释,N:注释,X:或者)

# | *1 | *2 | *3 |output|  
1 |  N |  N |  N |error |
2 |  N |  N |  Y |  1   |
3 |  N |  Y |  N |  1   |
4 |  N |  Y |  Y |  1   |
5 |  Y |  N |  N |  2   |
6 |  Y |  N |  Y |  1   |
7 |  Y |  Y |  N |error |
8 |  Y |  Y |  Y |  1   |

1,7是错误,这是正常的。(模糊且没有自动转换)
2似乎构造函数具有更高的优先级,但为什么呢? 3,5很容易理解。
4很奇怪,因为它没有调用显式的。为什么呢?
6可能是由于'显式'或构造函数具有更高的优先级。哪一个是原因? 8似乎构造函数具有更高的优先级,但为什么呢?
有人可以提供一些解释吗?谢谢!

1 个答案:

答案 0 :(得分:2)

一个非常好的问题。

首先,explicit并不意味着“如果需要进行显式转换,则优先考虑”。这意味着“这个东西只能被明确调用”。因此,它会创建一些无法调用的情况,而不是强制在其他情况下调用它。

要考虑的另一件事是static_castdirect initialization,而将参数传递给函数是copy initialization。除其他外,复制初始化从不使用显式构造函数。另外需要注意的是,直接初始化需要使用类的构造函数(显式或非显式)。虽然这并不意味着转换不能执行直接初始化:它可以用于转换构造函数的参数,如果构造函数是编译器生成的副本,那么它将看起来像转换函数执行直接初始化(而实际上它是由复制构造函数执行)。尝试声明复制构造函数而不定义它(禁用复制技术),你会发现转换函数不再适用于直接初始化上下文:它将编译,但会导致链接错误。

考虑到这一点:

  1. 显而易见的。
  2. 直接初始化需要一个构造函数,因此会调用它。
  3. 显而易见的。
  4. 和2一样,真的。声明转换函数explicit只会阻止它被隐式调用,它不会强制在显式上下文中使用它。
  5. 显而易见的。
  6. 同样,直接初始化需要一个构造函数,它允许使用显式的。
  7. 显而易见的。
  8. 另一个直接初始化案例。