我是靠谱客的博主 无辜烧鹅,最近开发中收集的这篇文章主要介绍为什么要用explicit指定构造函数,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

看到一篇文章,对于用explicit关键字限定构造函数的作用,说的简单明了,记录一下。
Why You Should Always Use explicit Constructors

C++的重载规则允许通过单参数构造函数将一个类型转换为另一个类型,编译器对于这种情况一般不会警告,因此可能会出现隐晦的错误。而关键字explicit关键字可以控制这种错误的发生。

例子

class A {};

class B {
public:
    B() {}
    B(A const&) {}
};

void f(B const&) {}

int main() {
    A obj;
    f(obj);

    return 0;
}

上述代码中,有两个简单的类A、B,其中B有一个接受A对象的单参数构造函数。在调用函数f时,程序默默调用了B类的单参数构造函数,构造了一个临时的B对象作为f函数的参数。其main函数过程等同于下面的代码:

int main() {
    A obj;
    {
        B obj_arg0(obj);
        f(obj_arg0);
    }
    return 0;
}

在这个例子中,构造了一个临时变量B似乎没有太大影响,但是如果B类的那个单参数构造函数相当耗费资源,或者f函数从他的参数(即B对象)中存储了数据,这种情况应该是不应该发生的。因为B类的这个临时对象在调用完函数f后就会被销毁,而f函数从这个对象中存储的数据则是无效的了。

解决办法

解决办法就是explicit关键字。修改代码如下(在单参数构造函数前添加explicit关键字)。

class A {};

class B {
public:
    B() {}
    explicit B(A const&) {}
};

void f(B const&) {}

int main() {
    A obj;
    f(obj);
    return 0;
}

此时编译则会报错:
在这里插入图片描述
编译器无法为我们自动调用B对象的单参数构造函数创建临时对象,因为explicit关键字的限制。而如果确实想要这样做,则需要手动调用这个构造函数。修改main函数为:

int main() {
    A obj;
    f(B(obj));
    return 0;
}

此时编译就可以通过,程序正常执行。这样可以避免并非我们意愿的构造导致的潜在bug。

需要注意的是,带默认参数的多参数构造函数同样适用这种情况:

class A {};

class B {
public:
    B() {}
    explicit B(A const&) {}
};

class C {
public:
    C() {}
    C(B const&, A const& a = A()) {}
};

void f(B const&) {}

void f1(C const&) {}

int main() {
    B obj;
    f1(obj);
    return 0;
}

对于上述代码的编译,编译器同样也没有任何的报错或者警告,程序调用了C类的第二个构造函数。因此需要把C类修改为:

class C {
public:
    C() {}
    explicit C(B const&, A const& a = A()) {}
};

以避免潜在的错误。

最后

以上就是无辜烧鹅为你收集整理的为什么要用explicit指定构造函数的全部内容,希望文章能够帮你解决为什么要用explicit指定构造函数所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部