c++ - (涉及显式)运算符和构造函数转换的优先级

标签 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 好像constructor有更高的优先级,但是为什么呢?
3、5很容易理解。
4 很奇怪,因为它没有调用显式的。为什么?
6 可能是由于“显式”或具有更高优先级的构造函数。是哪一个原因? 8 似乎构造函数的优先级更高,但为什么呢?

有人可以提供一些解释吗?谢谢!

最佳答案

一个很好的问题。

首先,显式 并不意味着“如果需要显式转换,则优先”。意思是“这个东西只能显式调用”。所以它创造了一些不能调用它的情况,而不是强制在其他情况下调用它。

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

考虑到这一点:

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

关于c++ - (涉及显式)运算符和构造函数转换的优先级,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34544899/

相关文章:

c++ - vector 下标超出范围 - 冒泡排序

c++ - 将流运算符 >> 评估为 bool 值

c - memcpy 问题将负值从 int8_t 转换为 int16_t

c++ - 构造函数的显式关键字的使用

c++ - 构造函数采用引用参数的显式修饰符

c++ - 显式关键字是什么意思?

C++ 转换问题

c++ - 使用 GDI+ 填充部分圆角矩形

c++ - 当包含头文件的文件不在根项目文件夹中时如何包含头文件?

rust - 我可以在类型转换期间重用结构体字段而不调用 .clone() 吗?