使用隐式构造函数还是隐式转换运算符将一个类型转换为另一个类型更好?

8
假设我们有一个过程 void f(X2);。进一步假设我们有类型 X1X2,它们没有共享继承层次结构。
我们希望这样调用它:f(X1 {}),并且让 X1 隐式转换为 X2。我们有两种实现此目的的选项:
struct X2 {};
struct X1 { operator X2(); };

struct X1 {};
struct X2 { X2(const X1&); };

就实现而言,这两种方式在定义顺序和访问私有数据的方式上存在实际差异。

但是从用户的角度来看,这两种方法是否会有不同的行为?如果有,哪一种更可取?

即使我们将两者都标记为explicit,这个问题仍然保持不变。唯一的区别是,在前一种情况下只能通过构造函数进行转换,而static_cast可以同时使用两种方法。


2
一个实际区别是“X2 是否知道 X1?”与“X1 是否知道 X2?”之间的区别。 - Eljay
最好使用显式转换。隐式转换可能会在以后导致不愉快的意外。C++ 核心指南 - C.164:避免使用隐式转换运算符 - Richard Critten
@RichardCritten,您链接的指南中的示例很有趣,因为它不鼓励从C字符串隐式转换为std::string,但反过来是可以的,并且是标准库的一部分。我面临的用例与此非常相似。 - Post Self
1
如果转换涉及构建新对象,请使用构造函数。 - john
@john,你的答案背后的原因是什么?也可以提取相关数据并使用该数据调用X2的公共构造函数。 - Post Self
1个回答

0

这两种方法在功能上是等效的,因此您可以定义这两种类型的转换,即使其中一种类型是您无法修改的类,或者根本不是类,例如基本类型。

在隐式情况下,这两个选项都允许您调用f(X1{}),在显式情况下,它们都允许f(X2{X1{}})。第二个选项直接使用转换构造函数,而第一个选项使用X2的复制或移动构造函数,该构造函数从转换运算符中获取其参数。实际的复制或移动操作将被省略,因此性能上没有区别。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接