我浏览了很多与转换相关的问题,但似乎没有人以这种方式讨论显式关键字。 这是代码:
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似乎构造函数具有更高的优先级,但为什么呢?
有人可以提供一些解释吗?谢谢!
答案 0 :(得分:2)
一个非常好的问题。
首先,explicit
并不意味着“如果需要进行显式转换,则优先考虑”。这意味着“这个东西只能被明确调用”。因此,它会创建一些无法调用的情况,而不是强制在其他情况下调用它。
要考虑的另一件事是static_cast
是direct initialization,而将参数传递给函数是copy initialization。除其他外,复制初始化从不使用显式构造函数。另外需要注意的是,直接初始化需要使用类的构造函数(显式或非显式)。虽然这并不意味着转换不能执行直接初始化:它可以用于转换构造函数的参数,如果构造函数是编译器生成的副本,那么它将看起来像转换函数执行直接初始化(而实际上它是由复制构造函数执行)。尝试声明复制构造函数而不定义它(禁用复制技术),你会发现转换函数不再适用于直接初始化上下文:它将编译,但会导致链接错误。
考虑到这一点:
explicit
只会阻止它被隐式调用,它不会强制在显式上下文中使用它。