说实话,从来没有感觉到这个关键字有用,直到今天。
explicit的意思是明显的,和它相对应的一个词是implicit意思是隐藏的。
我参考了MSDN和《c++标准程序库》对这个关键字的描述,并参考了网络上对这个关键字的解释。现将它的使用方法和总结记录如下:
首先这个关键字只能用在类构造函数。它的作用是不能进行隐式转换。
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; //这样是不行的,关键字取消了隐式转换,除非类实现操作符“=”的重载。
这是编译器(vs2005)显示:cannot convert from 'int' to 'gxgExplicit'。
从这里也就看出这个关键字的作用是将编译器隐式转换的功能给屏蔽掉。
MSDN上有一个注意点描述了下面的事实,当构造函数参数超过两个时自动取消隐式转换。例如
class gxgExplicit
{
private:
int _size;
int _age;
public:
explicit gxgExplicit(int age, int size)
{
_age = age;
_size = size;
}
};
这是有没有关键字效果是一样的。那就是相当于有这个关键字。
但是另外一种情况例外:其中只有一个必须输入的参数,其余的为有默认值的参数。
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;
}
};
这样的情况下相当于一个参数的效果。
到现在为止。这个关键字就是这么用了。
In C++ it is possible to declare constructors for a class, taking a single parameter, and use those constructors for doing type conversion. For example:
class A {
public :
A( int );
};
void f(A) {}
void g()
{
A a1 = 37 ;
A a2 = A( 47 );
A a3( 57 );
a1 = 67 ;
f( 77 );
}
A declaration like:
A a1 = 37;
says to call the A(int) constructor to create an A object from the integer value. Such a constructor is called a "converting constructor".
However, this type of implicit conversion can be confusing, and there is a way of disabling it, using a new keyword "explicit" in the constructor declaration:
class A {
public :
explicit A( int );
};
void f(A) {}
void g()
{
A a1 = 37 ; // illegal
A a2 = A( 47 ); // OK
A a3( 57 ); // OK
a1 = 67 ; // illegal
f( 77 ); // illegal
}
Using the explicit keyword, a constructor is declared to be
"nonconverting", and explicit constructor syntax is required:
class A {
public :
explicit A( int );
};
void f(A) {}
void g()
{
A a1 = A( 37 );
A a2 = A( 47 );
A a3( 57 );
a1 = A( 67 );
f(A( 77 ));
}
Note that an expression such as:
A(47)
is closely related to function-style casts supported by C++. For example:
double d = 12.34;
int i = int(d);