explicit关键字只能用在类内部的构造函数声明。以限制单参数的构造函数进行隐式转换。多参数的构造函数不能进行隐式转换。
在c++中,当函数传参时,编译器被允许隐式转换。言外之意即编译器可以使用形参的单参数构造函数将实参数隐士转化为形参对象。例如:
class Foo
{
public:
// single parameter constructor, can be used as an implicit conversion
Foo (int foo) : m_foo (foo)
{}
int GetFoo () { return m_foo; }
private:
int m_foo;
};
void DoBar (Foo foo)
{
int i = foo.GetFoo ();
}
int main ()
{
DoBar (42);
}
在main函数中我们看到DoBar的实参是int型,而非Foo类型。此时当进行参数传递时编译器就会进行隐式转换,即:以42作为参数调用Foo的单参数构造函数,构造一个Foo对象,将此对象作为实参传递给DoBar。
explicit关键字的作用就是阻止编译器的隐式转换。
假设你有一个类String:
class String {
public:
String (int n);//allocate n bytes to the String object
String(const char *p); // initializes object with char *p
};
现在你对它进行赋值:
String mystring='x';
此时char 'x' 将会隐士转化为int, 并将转化后的值作为参数调用String (int n),实际结果为分配了'x'字节的空间。为了避免出现此种隐式转换,可以使用关键字explicit:
class String {
public:
explicit String (int n); //allocate n bytes
String(const char *p); // initialize sobject with string p
};
在c++中只有一个参数的构造函数是一个可以被编译器隐士转换的函数,编译可以将其参数转化为其类对象。
有时候我们需要这种隐式转化:当你有一个类具有构造函数String(const char* s),而且你将一个const char*类型的实参传递给一个以String作为形参的函数,此时编译器就刚好将const char *实参转化为String对象,而此时的隐式转化恰好是我们需要的。
有些时候这种隐式转化却是多余的,这时使用explicit声明单参数的构造函数即可,当出现隐式转换的情况时,编译器就会报错:
class Buffer { explicit Buffer(int size); ... }
void useBuffer(Buffer& buf);
useBuffer(4);
当我们调用useBuffer(4);编译器就会报错,以阻止隐式转化。
参考链接:
What does the explicit keyword in C++ mean?