1.什么是显式构造函数?

首先要理解什么是隐式构造函数,并且弄清它的优缺点。

#include <iostream>
using std::cout;
using std::endl;

class complexNumbers {
double real, img;
public:
complexNumbers() : real(0), img(0) { }
complexNumbers(const complexNumbers& c) { real = c.real; img = c.img; }
complexNumbers( double r, double i = 0.0) { real = r; img = i; }
friend void display(complexNumbers cx);
};
void display(complexNumbers cx){
cout<<"Real Part: "<<cx.real<<"Imag Part: "<<cx.img<<endl;
}

int main() {
complexNumbers one(1);
complexNumbers five = 5;
display(one);
display(five);
return 0;
}

在这段代码中,我们定义一个复数的模型,并且定义了三个构造函数,一个默认构造函数(第一个),一个复制构造函数(第二个),第三个就是帮助我们实现隐式构造的构造函数。我们在主程序中使用了这个函数定义了两个对象:

输出为:

Real Part: 1 Imag Part: 0

Real Part: 5 Imag Part: 0

此时并没有什么问题,我们在主程序中加入一句话:display(300); 然后看结果,多打印了一行:

Real Part: 300 Imag Part: 0

这并非我们希望出现的结果,那这是如何发生的呢?

这里display函数发现传入的是一个数字300时,与它期待的类型(complexNumbers)不符合,它就隐式调用了构造函数进行对象的构造,产生一个临时complexNumbers的实例对象。这种情况发生在存在可以接受一个参数的构造函数中(除复制构造函数)。

解决这个问题的方式就是强迫编译器必须使用显式构造的方式创建对象,这要在构造函数前使用explicit 关键字。回到这个例子,加上explicit后程序无法编译,这样就解决了该问题。如果还想方便使用的话只能如此显式创建对象:

display(complexNumbers(200));

2.使用建议

在Google Style中,有明文要求在可以接受一个参数的构造函数(除复制构造函数)中必须使用explicit关键字防止这样的情况。