C++之explicit用法

  • Post author:
  • Post category:其他


explicit关键字是禁止隐式调用构造函数。什么是隐式调用构造函数呢,先看下面一个简单例子。

struct test1
{
    //explicit
    test1(int a, int b = 0) : x(a), y(b){}
    test1 operator+(const test1 &t)
    {
        return test1(x + t.x, y + t.y);
    }

    int x, y;
};

int main()
{
    test1 x(5, 6);
    test1 x1 = x + 1;
    cout << x1.x << ' ' << x1.y << endl;
    return 0;
}

代码中位于主函数内,可以看到有一个+运算,这里的+运算可能会引起不少人的注意。有些小伙伴可能会问:类内没有声明+运算符可以和int数值计算呀,为什么要这么写?这么写能编译通过吗?

其实这段代码是可以编译通过并且正确运行的,其运行结果输出为6 6。

下面来解释一下这段代码为什么可以通过:

这段代码中,巧妙的使用了test1这个类的构造函数,注意看这个构造函数,他需要两个参数,但是呢,第二个参数可以选填。这样一来,这个类构造时,传入一个参数,也是可以创建一个对象的。在调用operator+的时候,由于后面是一个数字,而这个数字恰好可以转换为test1类对象,因此,这里编译器会隐式的调用类的构造函数,这一行代码经过编译器处理后,可以理解为下面这样

test1 x1 = x + test1(1);

编译器还是非常智能的,他已经会把能匹配到的构造函数自动调用起来,但是有些时候,我们设计的类可能并不希望其隐式调用,那怎么办呢?就需要用到C++中一个关键字:explicit。

当我们将上面代码中explicit取消掉注释的时候,这段代码编译时就会报错,这样就防止了编译器太过智能,隐式调用构造函数的问题了。

在C++11之前,explicit只能防止上面说的这样,构造函数可以传入一个参数的情况。从C++11版本开始,explicit也可以防止构造函数传递多个参数的时候,使用初始化列表进行隐式调用。下面为C++11的示例

struct test2
{
    test2(int a, int b) { cout << "test2(int a,int b)..." << endl; }
    explicit test2(int a, int b, int c) { cout << "explicit 3 args version" << endl; }
};

void test2_fun(const test2 &x)
{
    cout << "test2_fun()" << endl;
}
int main()
{
    test2 t2_1(1, 1);
    test2 t2_2{1, 2};
    test2 t2_3{3, 3, 3};
    test2 t2_4 = {4, 4};
    //test2 t2_5 = {5, 5, 5};       // 报错,编译器不允许隐式调用构造
    test2_fun(t2_3);
    test2_fun({1, 2});
    //test2_fun({1,2,3});           // 报错,编译器不允许隐式调用构造
    return 0;
}



版权声明:本文为uhlgjd原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。