explicit主要是用来修饰类的构造函数,被修饰的构造函数的类,不能发生相应的隐式类型转换,只能以显示的方式进行类型转换。类构造函数默认情况下声明为隐式的即implicit。
1、explicit 修饰构造函数时,可以防止隐式转换和复制初始化
class gxgExplicit //没有关键字explicit的类 { public: int _size; gxgExplicit(int size) { _size = size; } }; //下面是调用 gxgExplicit gE1(24); //这样是没有问题的 gxgExplicit gE2 = 1; //这样也是没有问题的 gxgExplicit gE3; //这样是不行的,没有默认构造函数 gE1 = 2; //这样也是没有问题的 gE2 = 3; //这样也是没有问题的 gE2 = gE1; //这样也是没有问题的
但是假如gxgExplicit修改为Stack,我们的_size代表的是堆栈的大小,那么调用的第二句就显得不伦不类,而且容易让人疑惑。这并不是可以让代码阅读者明白和接受的形式,虽然它是合法的(编译器可以通过编译)。这是因为编译器默认情况下有隐式转换的功能,你输入gE2 = 1就编译成同第一句相同的结果。所以,explicit就派上了用场。修改代码为:
class gxgExplicit { public: int _size; explicit gxgExplicit(int size) { size = size; } }; //继续上面的调用: gxgExplicit gE1(24); //这样是没有问题的 gxgExplicit gE2 = 1; //这样是不行的,关键字取消了隐式转换 gxgExplicit gE3; //这样是不行的,没有默认构造函数 gE1 = 2; //这样是不行的,关键字取消了隐式转换 gE2 = 3; //这样是不行的,关键字取消了隐式转换 gE2 = gE1; //这样是不行的,关键字取消了隐式转换,除非类实现操作符“=”的重载。
当构造函数参数超过两个时自动取消隐式转换。这是有没有关键字效果是一样的。那就是相当于有这个关键字。
但是另外一种情况例外:其中只有一个必须输入的参数,其余的为有默认值的参数。
class gxgExplicit { private: int _size; int _age; public: explicit gxgExplicit(int age,int size = 0) { _age = age; _size = size; } }; class gxgExplicit { private: int _size; int _age; int _hight; public: explicit gxgExplicit(int age,int size = 0) { _age = age; _size = size; _hight = hight; } };
2、explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外
标准数据之间会进行 隐式类型安全转换。
struct A { A(int) { } operator bool() const { return true; } }; struct B { explicit B(int) {} explicit operator bool() const { return true; } }; void doA(A a) {} void doB(B b) {} int main() { A a1(1); // OK:直接初始化 A a2 = 1; // OK:复制初始化 A a3{ 1 }; // OK:直接列表初始化 A a4 = { 1 }; // OK:复制列表初始化 A a5 = (A)1; // OK:允许 static_cast 的显式转换 doA(1); // OK:允许从 int 到 A 的隐式转换 if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化 B b1(1); // OK:直接初始化 B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化 B b3{ 1 }; // OK:直接列表初始化 B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化 B b5 = (B)1; // OK:允许 static_cast 的显式转换 doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换 if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换 bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化 return 0; }
参考:
https://www.cnblogs.com/QG-whz/p/4472566.html
https://www.jb51.net/article/41526.htm
https://www.cnblogs.com/hjxzjp/p/11768674.html
原文:https://www.cnblogs.com/calla/p/13655027.html