c++ - 转换构造函数和运算符都存在并且涉及显式性时的行为
问题描述
我有一段代码,其中有转换构造函数和转换运算符。
#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;
}
- 如果两者都是非显式的。我收到一个编译器错误,说第一个表达式不明确。第二个表达式调用构造函数。
- 如果只有 operator 是显式的,则两种转换都使用构造函数。
- 如果只有构造函数是显式的,则第二个转换调用构造函数,第一个使用运算符。
- 如果两者都是显式的,我只能编译第二个表达式。它使用构造函数。
我不明白为什么在第二种情况下的第二个表达式中没有调用转换运算符。
我还期望在第四个场景(类似于第一个场景)中出现歧义错误,但选择了构造函数。
我使用带有 -pedantic 和 -std=c++17 标志的 g++ 7.4.0 进行编译。
解决方案
首先,c-style cast执行static_cast
,然后
(强调我的)
1) 如果存在 from
expression
to的隐式转换序列new_type
,或者如果直接初始化对象或类型new_type
from的引用的重载决议expression
会找到至少一个可行的函数,则返回如同 by 初始化static_cast<new_type>(expression)
的虚变量Temp
new_type Temp(expression);
,这可能涉及隐式转换,对构造函数的new_type
调用或对用户定义的转换运算符的调用。
因此,给定(ClassInt)floatObj;
(初始化为 if ClassInt Temp(floatObj);
),转换构造函数将始终是首选,它将直接用于构造 a ClassInt
。虽然应用转换运算符需要从floatObj
to隐式转换ClassInt
(然后在概念上复制初始化临时ClassInt
)。
对于第一种情况,您观察到的结果似乎与上述摘要略有不同,
- 如果两者都是非显式的。我收到一个编译器错误,说它不明确。
只有第一个表达式会导致模棱两可的问题,第二个表达式将使用转换构造函数。
顺便说一句:我尝试使用gcc 7.3.0,结果符合预期。
为了回答您的问题,
我不明白为什么在第二种情况下的第二个表达式中没有调用转换运算符。
因为转换构造函数是第二个表达式(c-ctyle cast)的首选。
我还期望在第四个场景(类似于第一个场景)中出现歧义错误,但选择了构造函数。
同上,第二个表达式首选转换构造函数;第一个表达式会导致错误,因为转换构造函数和转换运算符都标记为explicit
.
另请注意,第一个表达式需要隐式转换,那么转换构造函数或转换运算符是否被标记为很explicit
重要。另一方面,第二个表达式是显式转换,它不在乎。
推荐阅读
- sql-server - SQL Server:BLOB/CLOB 值是否通过引用存储在行中或其他地方?
- javascript - 如何防止javascript解构赋值中的函数参数被具有相同ID的DOM元素覆盖
- c# - 具有共享代码和不同代码的 C# 构造函数
- sql - 使用链接服务器访问同义词
- python - 我可以编写一个函数,从两个不同的表中获取数据,将其转换并保存到 Django 中的第三个表中吗?
- javascript - 改变弹性列的宽度?
- ngrx - 具有新 createreducer 功能的 INITIAL_STATE 注入令牌
- visual-studio-code - 有没有办法在 Visual Studio Code 中自动保存终端命令
- c# - c# 8.0 switch 表达式返回类型和空值
- swift - SwiftUI 中有没有办法根据具有值的可选绑定返回不同的视图?