原文定义为:
Normally, if a constructor takes one argument, it can be used as a conversion. For instance, if you define Foo::Foo(string name) and then pass a string to a function that expects a Foo, the constructor will be called to convert the string
into a Foo and will pass the Foo to your function for you. This can be convenient but is also a source of trouble when things get converted and new objects created without you meaning them to. Declaring a constructor explicit prevents it from
being invoked implicitly as a conversion.
下面这段代码是编译不过去的。
#include <iostream> #include <stdio.h> using namespace std; class CTest { public: explicit CTest(const CTest& c) : m_i(c.m_i) /// copy constructor { printf("in the copy constructor(CTest).\n"); } explicit CTest(int i) : m_i(i) /// constructor { printf("in the constructor(CTest).\n"); } CTest() /// defalut constructor { printf("in the defalut constructor(CTest)\n"); } public: int m_i; /// }; CTest func(CTest &c) { c.m_i = 1; return c; } int main() { CTest c1, c2; c2 = func(c1); printf("c1.m_i = %d, c2.m_i = %d\n", c1.m_i, c2.m_i); return 0; }
func函数将对象c通过值传递返回,隐式的调用了CTest的拷贝构造函数,但是CTest拷贝构造函数使用了explicit关键字,禁止了隐式转换的功能,如果将explicit关键字去掉就可以编译。
结果输出为
in the defalut constructor(CTest) in the defalut constructor(CTest) in the copy constructor(CTest). c1.m_i = 1, c2.m_i = 1
还是这个类CTest,如果main()如下:
int main() { CTest c = 1; printf("c.m_i = %d\n", c.m_i); return 0; }
仍旧不能正常编译,原因是:
CTest c = 1; 这句话在编译器看来是不正确的,但是编译器可以发现CTest可以根据一个int来构造,所以调用了构造函数,生成了一个临时的对象,然后将这个临时变量拷贝给了c。
可以把这句话翻译成为:
CTest temp(1);
CTest c = temp;
可见,程序分别隐式的调用了明确构造函数和拷贝构造函数,但是CTest类中的明确构造函数和拷贝构造函数使用了explicit来修饰,导致程序无法正确编译,如果将这两个explicit去掉,则运行结果如下:
in the constructor(CTest). c.m_i = 1
总之, explicit关键字用来修饰构造函数,表面该构造函数是显示的,如果进行了构造函数的隐式操作,根据编译器的不同,有些会告警,而有些会发生编译错误。