explicit小结

150 阅读2分钟

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关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数.特例