我有一段代码,其中同时包含转换构造函数和转换运算符。
#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;
}
- 如果两者都不明确。我收到一个编译器错误,说第一个表达式不明确。第二个表达式调用构造函数。
- 如果只有运算符是显式的,则两个转换都使用构造函数。
- 如果只有构造函数是显式的,则第二次转换调用构造函数,第一次使用运算符。
- 如果两者都是显式的,我只能编译第二个表达式。它使用构造函数。
我不明白为什么在第二个场景的第二个表达式中没有调用转换运算符。
我还期望在第四种情况(类似于第一种情况)中出现歧义错误,但选择了构造函数。
我使用带有 -pedantic 和 -std=c++17 标志的 g++ 7.4.0 进行编译。
最佳答案
首先,c-style cast表演 static_cast
, 然后
(强调我的)
1) If there is an implicit conversion sequence from
expression
tonew_type
, or if overload resolution for a direct initialization of an object or reference of typenew_type
fromexpression
would find at least one viable function, thenstatic_cast<new_type>(expression)
returns the imaginary variableTemp
initialized as if bynew_type Temp(expression);
, which may involve implicit conversions, a call to the constructor ofnew_type
or a call to a user-defined conversion operator.
所以给出(ClassInt)floatObj;
(初始化为 ClassInt Temp(floatObj);
),转换构造函数将始终是首选,它将直接用于构造 ClassInt
.应用转换运算符时需要从 floatObj
进行隐式转换至 ClassInt
(然后在概念上复制初始化临时 ClassInt
)。
对于第一种情况,您观察到的结果似乎与上述总结略有不同,
- 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/