c++ - 存在转换构造函数和运算符并且涉及显式时的行为

标签 c++ implicit-conversion explicit explicit-conversion

我有一段代码,其中同时包含转换构造函数和转换运算符。

#include <iostream>
struct ClassFloat;

struct ClassInt{
    int value;
    ClassInt(int c) : value(c){std::cout << "From integer\n";};
    ClassInt(ClassFloat x);
    //explicit ClassInt(ClassFloat x);
};

struct ClassFloat{
    float val;
    explicit operator ClassInt() {std::cout << "Conversion operator called\n"; return ClassInt{999};}
    //operator ClassInt() { std::cout << "Conversion operator called\n"; return ClassInt{999};}
};

ClassInt::ClassInt(ClassFloat x){
    std::cout << "Conversion constructor called!\n";
    value = (int)x.val;
}

int main(){
    ClassFloat floatObj{3.5f};
    ClassInt instance1 = floatObj;           // (1)
    ClassInt instance2 = (ClassInt)floatObj; // (2)
    return 1;
}
  1. 如果两者都不明确。我收到一个编译器错误,说第一个表达式不明确。第二个表达式调用构造函数。
  2. 如果只有运算符是显式的,则两个转换都使用构造函数。
  3. 如果只有构造函数是显式的,则第二次转换调用构造函数,第一次使用运算符。
  4. 如果两者都是显式的,我只能编译第二个表达式。它使用构造函数。

我不明白为什么在第二个场景的第二个表达式中没有调用转换运算符。

我还期望在第四种情况(类似于第一种情况)中出现歧义错误,但选择了构造函数。

我使用带有 -pedantic 和 -std=c++17 标志的 g++ 7.4.0 进行编译。

最佳答案

首先,c-style cast表演 static_cast , 然后

(强调我的)

1) If there is an implicit conversion sequence from expression to new_type, or if overload resolution for a direct initialization of an object or reference of type new_type from expression would find at least one viable function, then static_cast<new_type>(expression) returns the imaginary variable Temp initialized as if 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.

所以给出(ClassInt)floatObj; (初始化为 ClassInt Temp(floatObj); ),转换构造函数将始终是首选,它将直接用于构造 ClassInt .应用转换运算符时需要从 floatObj 进行隐式转换至 ClassInt (然后在概念上复制初始化临时 ClassInt)。

对于第一种情况,您观察到的结果似乎与上述总结略有不同,

  1. If both are non-explicit. I get a compiler error saying it is ambiguous.

只有第一个表达式导致模棱两可的问题,第二个表达式将使用转换构造函数。

顺便说一句:我试过 gcc 7.3.0 , 给出了预期的结果。

回答你的问题,

I didn't understand why conversion operator wasn't called at the second expression in the second scenario.

因为转换构造函数更适合第二个表达式(c-ctyle 转换)。

I was also expecting an ambiguity error in the fourth scenario (similar to the first scenario) but constructor was picked.

同上,第2个表达式优先使用转换构造函数;第一个表达式会导致错误,因为转换构造函数和转换运算符都标记为 explicit .

还要注意第一个表达式需要隐式转换,那么无论是转换构造函数还是转换运算符都标记为explicit确实很重要。另一方面,第二个表达式是 explicit conversion ,这并不关心。

关于c++ - 存在转换构造函数和运算符并且涉及显式时的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57373901/

相关文章:

C# 锯齿状数组 : compiler cannot implicitly convert type 'char[]' to 'int[]' . 为什么?

c++ - 如果 T 可转换为 U,则将 class<T> 转换为 class<U>

c++ - C++ 表达式中什么时候会发生隐式强制转换?

app-store - 从通配符应用程序ID升级到显式应用程序ID,以允许推送通知

java - 隐式 super 构造函数 Shape2D() 未定义。关于 "include Java.awts.Color"

python - C++ 输出与 Python 不同的消息(从串口读取)

c++ - 如何以编程方式配置鼠标增强指针精度

c++ - 在 main() 之外的 Qt 中创建一个窗口?

c++ - QT如何在Designer Class上使用模板

c++ - 显式特化 - template-id 与任何模板声明都不匹配