我有一段代码,其中既有转换构造函数又有转换运算符。
#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风格的演员表进行表演static_cast
,然后
(强调我的)
1)如果存在的隐式转换序列从
expression
至new_type
,或者如果对象或类型的引用的直接初始化重载解析new_type
从expression
将找到至少一个可行的功能,然后static_cast<new_type>(expression)
返回虚变量Temp
初始化为如果通过new_type Temp(expression);
,这可能涉及隐转换,对构造函数的new_type
调用或对用户定义的转换运算符的调用。
因此,给定(ClassInt)floatObj;
(就像一样初始化ClassInt Temp(floatObj);
),转换构造函数将始终是首选,它将直接用于构造ClassInt
。同时施加转换运算符需要来自隐式转换floatObj
到ClassInt
(再复制初始化临时ClassInt
在概念)。
对于上述第一种情况,您的观察结果似乎与上述摘要有些不同,
- 如果两者都不明确。我收到一个编译器错误,说它模棱两可。
只有第一个表达式导致模棱两可的问题,第二个表达式将使用转换构造函数。
顺便说一句:我尝试了gcc 7.3.0,它给出了预期的结果。
为了回答您的问题,
我不明白为什么在第二种情况下第二个表达式没有调用转换运算符。
因为第二个表达式(c-ctyle强制转换)首选使用转换构造函数。
我还期望在第四种情况下(与第一种情况类似)出现歧义错误,但是选择了构造函数。
与上面相同,第二个表达式首选转换构造函数;第一个表达式将导致错误,因为转换构造函数和转换运算符都标记为explicit
。
另请注意,第一个表达式需要进行隐式转换,因此是否将转换构造函数或转换运算符标记为必需explicit
。另一方面,第二个表达式是显式转换,它不在乎。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句