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关键字依然有效, 此时, 当调用构造函数时只传入一个参数, 等效于只有一个参数的类构造函数
posted on 2020-04-14 15:49  JJ_S  阅读(301)  评论(0编辑  收藏  举报