explicit概述
C++中的explicit关键字主要用于修饰只有一个参数的类构造函数。
它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式).
隐式构造和显示构造的区别可以从如下代码中体会一下:
class ExString // 没有使用explicit关键字的类声明, 即默认为隐式声明
{
public:
ExString(int size)
{
size_ = size; // string的预设大小
pstr_ = malloc(size + 1); // 分配string的内存
memset(pstr_, 0, size + 1);
}
ExString(const char *p)
{
int size = strlen(p);
pstr_ = malloc(size + 1); // 分配string的内存
strcpy(pstr_, p); // 复制字符串
size_ = strlen(pstr_);
}
private:
char *pstr_;
int size_;
};
int main(){
ExString string1(24); // 这样是OK的, 为CxString预分配24字节的大小的内存
ExString string2 = 10; // 这样是OK的, 为CxString预分配10字节的大小的内存
ExString string3; // 这样是不行的, 因为没有默认构造函数, 错误为: “CxString”: 没有合适的默认构造函数可用
ExString string4("aaaa"); // 这样是OK的
ExString string5 = "bbb"; // 这样也是OK的, 调用的是CxString(const char *p)
ExString string6 = 'c'; // 这样也是OK的, 其实调用的是CxString(int size), 且size等于'c'的ascii码
string1 = 2; // 这样也是OK的, 为CxString预分配2字节的大小的内存
string2 = 3; // 这样也是OK的, 为CxString预分配3字节的大小的内存
string3 = string1; // 这样也是OK的, 至少编译是没问题的, 但是如果析构函数里用free释放_pstr内存指针的时候可能会报错, 完整的代码必须重载运算符"=", 并在其中处理内存释放
return 0;
}
main函数中,通过多种调用ExString构造函数的方式来构造对象,可以看到ExString string2 = 10是可以运行的,ExString string6 = 'c'这种方式也是可以运行的,这在代码编码中会产生的歧义,为了避免这种隐式的转化造成的误导,建议在编码过程中对只有一个函数的构造函数使用explicit.
多参构造函数下的explicit
上文说过当构造函数只有一个参数时,需要添加explicit来避免隐式转换,其实在多参的情况下也是有必要添加的,只是这属于特殊情况:
class ExString // 使用关键字explicit声明
{
public:
explicit ExString(int age, int size = 0)
{
age_ = age;
size_ = size;
...
}
ExString(const char *p)
{
...
}
private:
int age_;
int size_;
};
当除了第一个参数以外的其他参数都有默认值的时候, explicit关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数.特例