explicit关键字
【作用】:
explicit关键字只能用于修饰只有一个参数的类构造函数,它的作用是表明该构造函数是显式的,而非隐式的,跟它相对的另一个关键字是implicit,意思是隐藏的,类构造函数默认情况下声明为implicit。
显式声明和隐式声明的构造函数的区别如下例:
【示例1】
class Test
{
public:
Test(int m) {
m_iSize = m;
}
Test(char *p) {
m_pChar = p;
}
private:
int m_iSize;
char * m_pChar;
};
int main()
{
Test t1(10); // OK
Test t2 = 20; // OK
Test t3; // ERROR, 因为没有默认构造函数,
Test t4("aaaa"); // OK
Test t5 = "bbbb"; // OK
Test t6 = 'c'; // OK,调用的是Test(int m),且m等于'c'的ascii码
t1 = 1; // OK
t3 = t1; // OK
return 0;
}
Test t2 = 20;这句为什么可以呢? 因为在C++中, 如果构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象。
也就是说 "Test t2 = 20;" 这段代码, 编译器自动将整型转换为Test类对象, 实际上等同于下面的操作:
Test t2(10);
或
Test temp(10);
Test t2 = temp;
但是, 上面的代码中的m代表的是大小, 那么调用的"Test t6 = 'c';" 就显得不伦不类, 而且容易让人疑惑。
有什么办法阻止这种用法呢? 答案就是使用explicit关键字. 我们把上面的代码修改一下, 如下:
【示例2】
class Test
{
public:
explicit Test(int m) {
m_iSize = m;
}
Test(char *p) {
m_pChar = p;
}
private:
int m_iSize;
char * m_pChar;
};
int main()
{
Test t1(10); // OK
Test t2 = 20; // ERROR, 因为explicit关键字取消了隐式转换
Test t3; // ERROR, 因为没有默认构造函数,
Test t4("aaaa"); // OK
Test t5 = "bbbb"; // OK
Test t6 = 'c'; // ERROR, 因为explicit关键字取消了隐式转换
t1 = 1; // ERROR, 因为explicit关键字取消了隐式转换
t3 = t1; // ERROR,因为取消了隐式转换, 除非类实现操作符"="的重载
return 0;
}
explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了
当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数