详细的

如果您向C ++程序员询问显式关键字的含义,则大多数人会回答此关键字位于带有一个参数(或带有大量参数,但从第二个开始的所有参数均具有默认值)的构造函数声明之前,并防止隐式转换在初始化时输入类型。


class Simple { public: Simple(int a) : a_(a) {} private: int a_; }; class SimpleExplicit { public: explicit SimpleExplicit(int a) : a_(a) {} private: int a_; }; template <typename S> void someFunc(const S& s) { } int main(int, char**) { Simple s3 = 11; // SimpleExplicit se3 = 11; - COMPILE ERROR SimpleExplicit se3 = SimpleExplicit(11); someFunc<Simple>(11); // someFunc<SimpleExplicit>(11); - COMPILE ERROR someFunc<SimpleExplicit>(SimpleExplicit(11)); return 0; } 

在旧的C ++ 03中,关键字应用程序场景到此结束了,但是从C ++ 11开始,显式扩展了它的范围:现在,它不仅在具有一个参数的构造函数中,甚至在构造函数中都有意义。


在2011年,标准中添加了通用初始化,这应该清理动物园初始化从C ++继承自C的对象的动物园方法。在此,我将不详细讨论通用初始化,有关该主题的文章很多,易于通过关键字查找。 简而言之:建议使用花括号将对象初始化,实际上,这种扩展就是所谓的 从C继承的聚合初始化。


随着通用初始化的出现,对于具有0.2.3或更多参数的设计人员来说,显式有意义的含义是:


 class Simple { public: Simple() : a_(0), b_(0) {} Simple(int a) : a_(a), b_(0) {} Simple(int a, int b) : a_(a), b_(b) {} private: int a_, b_; }; class SimpleExplicit { public: explicit SimpleExplicit() : a_(0), b_(0) {} explicit SimpleExplicit(int a) : a_(a), b_(0) {} explicit SimpleExplicit(int a, int b) : a_(a), b_(b) {} private: int a_, b_; }; template <typename S> void someFunc(const S& s) { } int main(int, char**) { Simple s4 = {}; someFunc<Simple>({}); // SimpleExplicit se4 = {}; - COMPILE ERROR SimpleExplicit se4 = SimpleExplicit{}; // someFunc<SimpleExplicit>({}); - COMPILE ERROR someFunc<SimpleExplicit>(SimpleExplicit{}); Simple s5 = {11}; someFunc<Simple>({11}); // SimpleExplicit se5 = {11}; - COMPILE ERROR SimpleExplicit se5 = SimpleExplicit{11}; // someFunc<SimpleExplicit>({11}); - COMPILE ERROR someFunc<SimpleExplicit>(SimpleExplicit{11}); Simple s6 = {11, 22}; someFunc<Simple>({11, 22}); // SimpleExplicit se6 = {11, 22}; - COMPILE ERROR SimpleExplicit se6 = SimpleExplicit{11, 22}; // someFunc<SimpleExplicit>({11, 22}); - COMPILE ERROR someFunc<SimpleExplicit>(SimpleExplicit{11, 22}); return 0; } 

另外,从C ++ 11开始,explicit关键字也可以应用于类型转换运算符,也禁止隐式调用:


 class Simple { public: Simple() {} operator bool() const { return true; } }; class SimpleExplicit { public: explicit SimpleExplicit() {} explicit operator bool() const { return true; } }; int main(int, char**) { Simple s7{}; bool b7 = s7; SimpleExplicit se7{}; // bool be7 = se7; - COMPILE ERROR bool be7 = static_cast<bool>(se7); return 0; } 

总之,我建议在任何新的C ++代码中都使用通用初始化,并始终总是显式声明显式构造函数,除非隐式转换在语义上是合理的。

Source: https://habr.com/ru/post/zh-CN436296/


All Articles