可接受一个参数的构造函数需用 explicit 关键字限定
5.1.11 ID_missingExplicitConstructor
为了避免意料之外的类型转换,可接受一个参数的构造函数应该用 explicit 关键字限定。
示例:
class String {
public:
String(int capacity); // Non-compliant, missing ‘explicit’
....
};
例中 String 是一个字符串类,String(int) 用于设定字符串对象的初始容量,但下列代码可以通过编译:
String foo = 100; // Odd, the string is "100"?
void bar(const String&);
void baz() {
bar(100); // Unexpected implicit conversion
}
由于 String 类的构造函数接受一个 int 型参数,例中整数 100 可以被隐式转换为 String 类的对象,这种转换易造成意料之外的错误或开销。
应使用 explicit 关键字限定可接受一个参数的构造函数:
class String {
public:
explicit String(int capacity); // Compliant
....
};
这样从 int 到 String 的隐式转换会被禁止。在接口设计中,应尽量减少隐式转换以避免意料之外的问题。
例外:
class String {
public:
String(const String&); // Compliant
String(String&&); // Compliant
....
};
拷贝、移动构造函数可不受本规则约束,如果拷贝、移动构造函数被 explicit 关键字限定则无法再按值传递参数或按值返回对象。
另外,为了提高易用性,在类是构造函数参数的扩展、视图等情况下,可以不使用 explicit 关键字,但相关设计需要通过评审,本规则不放宽对这种情况的要求,如:
class String {
public:
String(const char*); // Non-compliant, manual review is required
....
};
class StringView {
public:
StringView(const String&); // Non-compliant, ditto
....
};
String s = "a"; // Easy to understand
StringView v = s; // Ditto
例中字符串字面常量转为字符串类对象、字符串对象转为字符串视图是易于理解的,但可能不便于审计工具进行量化分析,需要人工评审。
相关
参考
C++ Core Guidelines C.46
MISRA C++ 2008 12-1-3