C++面向对象编程:explicit关键字

explicit关键字的作用就是防止有一个参数的类构造函数进行隐式自动转换。

所以explicit只能用于修饰只有一个参数的类构造函数,表明该构造函数是显示的, 而非隐式的, 跟它相对应的另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为implicit(隐式)

explicit关键字只对有一个参数的类构造函数有效, 如果类构造函数参数大于或等于两个时, 是不会产生隐式转换的, 所以explicit关键字也就无效了。

在C++中,构造函数可以允许隐式类型转换,允许单参数构造函数将其参数类型自动转换为其类类型的对象,除非使用explicit关键字显式地禁止。

class CxString  // 没有使用explicit关键字的类声明, 即默认为隐式声明。 
{  
public:  
    char *_pstr;  
    int _size;  
    CxString(int size)  
    {  
        _size = size;                // string的预设大小  
        _pstr = malloc(size + 1);    // 分配string的内存  
        memset(_pstr, 0, size + 1);  
    }  
    CxString(const char *p)  
    {  
        int size = strlen(p);  
        _pstr = malloc(size + 1);    // 分配string的内存  
        strcpy(_pstr, p);            // 复制字符串  
        _size = strlen(_pstr);  
}  
//假设重载了”=“运算符和拷贝构造函数.  
};  

CxString string1(24);  

  正确:直接调用单参数构造函数CxString(int size),为CxString对象预分配24字节大小的内存。

CxString string4("aaaa");

  正确:直接调用CxString(const char* p)构造函数,使用C字符串"aaaa"初始化对象。

CxString string2 = 10;   

  正确:利用隐式类型转换,将整数10转换为CxString类型,等价于CxString string2(10);。

CxString string5 = "bbb";

  正确:通过隐式类型转换,将C字符串"bbb"转换为CxString对象,实质上调用CxString(const char* p)构造函数。

CxString string6 = 'c';

 正确:通过隐式类型转换,将字符'c'(其ASCII码值)作为整数传递给CxString(int size)构造函数。

string1 = 2;

 正确: 将整数2隐式转换为CxString类型,然后使用赋值操作。这里假设已重载赋值运算符,以处理CxString对象的赋值。

在C++中, 如果的构造函数只有一个参数时, 那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象。"CxString string2 = 10;"这段代码, 编译器自动将整型转换为CxString类对象, 实际上等同于下面的操作:

CxString string2(10);  

或  

CxString temp(10);  

CxString string2 = temp;  

"CxString string2 = 10;" 和"CxString string6 = 'c';" 显得不伦不类, 而且容易让人疑惑。可以在单个参数的构造函数前面使用explicit关键字,阻止这种隐式转换。

class CxString {
public:
    char *_pstr;
    int _size;
    explicit CxString(int size) {
        _size = size;                // 字符串的预设大小
        _pstr = static_cast(malloc(size + 1));    // 分配字符串的内存
        memset(_pstr, 0, size + 1);
    }
    explicit CxString(const char *p) {
        int size = strlen(p);
        _pstr = static_cast(malloc(size + 1));    // 分配字符串的内存
        strcpy(_pstr, p);            // 复制字符串
        _size = strlen(_pstr);
    }
    // 析构函数
    ~CxString() {
        free(_pstr);                  // 释放分配的内存
    }
    // 拷贝构造函数
    CxString(const CxString& other) : _size(other._size) {
        _pstr = static_cast(malloc(_size + 1));
        strcpy(_pstr, other._pstr);
    }
    // 赋值运算符
    CxString& operator=(const CxString& other) {
        if (this != &other) {  // 防止自我赋值
            char* newpstr = static_cast(malloc(other._size + 1));
            strcpy(newpstr, other._pstr);
            free(_pstr);
            _pstr = newpstr;
            _size = other._size;
        }
        return *this;
    }
};

 调用结果:

CxString string1(24);     // OK  

    CxString string4("aaaa"); // OK  

CxString string2 = 10;    // 不行, explicit关键字取消了隐式转换  

    CxString string6 = 'c';   // 不行, 调用的是CxString(int size), 且size等于'c'的ascii码, explicit关键字取消了隐式转换  

    CxString string3;         // 不行, 因为没有默认构造函数  

    string1 = 2;              // 不行, 因为取消了隐式转换  

    string2 = 3;              // 不行, 因为取消了隐式转换  

    string3 = string1;        // 不行, 因为取消了隐式转换, 除非类实现操作符"="的重载

  Effective C++:除非有一个好理由允许构造函数被用于隐式类型转换,否则我会把它声明为explicit,鼓励大家遵循相同的政策。

你可能感兴趣的:(c++,c++,java,jvm)