使用了构造函数而不是或类型转换运算符
Constructor used instead of or typecast operator
我得到了以下代码
class A {
private:
int n;
public:
A(int n) : n{n} {}
A(const A & a) : n{a.n} {}
};
class B {
private:
int m;
public:
B(int n) : m{n} {}
operator A() const { return A(m); }
operator int() const { return m; }
};
int main(int, char**)
{
B b{1};
(A)b; // Fails
static_cast<A>(b); // Fails
b.operator A(); // OK
}
失败
call of overloaded ‘A(B&)’ is ambiguous
(gcc,但VC++和clang似乎用同样的方式处理它)
我原以为这三件事会完全一样。使用B运算符A()的转换。显然情况并非如此。为什么?
通过显式地使用int()运算符可以很容易地解决这个问题,但我想要的是一个解释,而不是解决方案。
A
可以由int
或const A&
构造,B
可以转换为这两者,因此这些表达式是令人震惊的,因为编译器无法知道从B
创建某些A
的两个不同路径是否会导致相同的结果。
这是由于static_cast
确定可能的转换路径的方法:
如果
new_type
类型的临时对象可以用表达式声明和初始化,如new_type Temp(expression);
,这可能涉及隐式转换、对new_type
构造函数的调用或对用户定义的转换运算符的调用,则static_cast<type>(expression)
计算并返回该临时对象的值。(参考)
注意此部分:
可能涉及隐式转换、对
new_type
构造函数的调用或对用户定义的转换运算符的调用
可以将B
隐式转换为int
,然后从int
构造A
。
或者您可以根据转换运算符将B
转换为A
。
这就是在这里使用C样式或static_cast
时产生歧义的原因。
我建议将构造函数(A(int)
)设为explicit
,而不是运算符。这通常是被通缉的行为。这将导致static_cast<A>(b)
的无野心行为:使用operator A()
。
注意,A a = b;
是明确的:它将使用operator A()
,因为隐式转换更喜欢用户定义的转换(ref)
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 将内置类型变量传递给只有一个类类型参数的"+"运算符函数时自动类型转换的构造函数
- 自定义类型转换运算符在转发引用上调用时不起作用(当对象按值传递时有效)
- 模板化隐式类型转换运算符
- 具有重载类型转换运算符的函数对象崩溃
- 仅为某些模板专用化定义转换运算符:预期类型/预期类型说明符
- 类型转换运算符重载与 as 非成员函数
- 从类模板中排除转换运算符...<类型名 T>基于 T 上的特征
- 初始化中的模板转换运算符类型推导规则是什么?
- C++类型转换运算符
- C++:重载运算符.奇怪的类型转换运算符
- 忽略C++重载类型转换运算符
- 在 Visual Studio 10 中使用类型转换运算符重载时出现 C2440 错误
- 使用了构造函数而不是或类型转换运算符
- 模板类中的类型转换运算符 - 无论显式如何都调用
- 与类型转换运算符一起使用时条件运算符"?:"的编译器错误
- C++类型转换运算符代码,在 Visual Studio 2012 中无法编译,但在 Visual Studio 2005 中工作正常
- 为什么类型转换运算符不适用于继承的类?
- 重载类型转换运算符的语法
- 在 C++ 中定义类型转换运算符模板的正确方法是什么?