在设计公共API时,将构造函数设为显式是一种好习惯吗?
class A {
public:
//explicit A(int i){}
A(int i){}
};
void fun(const A& a) {}
int main() {
// If I use explicit for A constructor, I can prevent this mistake.
// (Or shall I call it as feature?)
fun(10);
}
或者我应该允许隐式转换,以允许用户以更少的输入来调用我的API?
答案 0 :(得分:9)
构造函数应该是显式的,除非隐式转换在语义上有意义(例如,将int
转换为A
是什么意思?)。减少打字不应成为指导该决定的标准。考虑可读性(这是隐式转换的主要参数)以及代码的理解程度。一个不直观的隐式演员会让代码的读者抓住他们的头脑。
P.S。:我现在似乎无法提出一个很好的例子,所以任何帮助都会受到赞赏。
答案 1 :(得分:5)
This是我在“DanielKrügler”的共鸣中找到的
如果我们开始设计C ++ 从今天开始,有一个很好的 机会,所有建设者和 转换功能是“明确的” 默认情况下,但用户可以制作 “隐”。唉,时间不可能 转过身来,我们必须忍受 目前的状态。这意味着我们 必须要小心 隐式构造函数(除了 复制/移动构造函数)。这是一个更安全的 规则使构造函数显式, 某种形式的转换是在哪里 涉及(即任何构造函数 参数类型U不同于 实际类型T)。
答案 2 :(得分:5)
是的,默认情况下是任何构造函数,可以使用一个参数调用 应该是明确的。遵循这条规则将避免微妙的错误 很难找到。
当然,这条规则有例外:
如果你的班级有,那么隐含的转换可能是可取的 围绕一个参数类型的包装器的语义。
复制构造函数不应该是显式的(否则你会松散 传值调用的可能性。)
答案 3 :(得分:1)
显式构造函数在类中使用,它消耗大量资源,如内存,构造时间等,以防止用户意外地创建此类的实例。由你决定你的类是否“足够”以使用显式构造函数。
答案 4 :(得分:1)
这取决于所涉及的成本,无论是语义还是性能。如果你的类的创建很昂贵,你应该防止它被意外地实例化。如果它是一个廉价的类来创建,那么隐式构造可以大大简化API用户的工作。