文章首发
【重学 C++】06 | C++该不该使用 explicit
引言
大家好,我是只讲技术干货的会玩code,今天是【重学C++】的第六讲,在 C++中,explicit
关键字作用于类的构造函数或类型转换操作符,以禁止隐式类型转换。今天,我们来聊聊到底该不该使用explicit
。
explicit的作用
在C++中,默认允许隐式转换,隐式类型转换是指在表达式中自动进行的类型转换,无需显式地指定转换操作。
struct Im {
Im();
Im(int);
};
void read_im(const Im&);
int main(int argc, char const *argv[])
{
Im i1;
Im i2 = Im();
Im i3 = Im(1);
Im i4 = {};
Im i5 = 1;
Im i6 = {1};
read_im({});
read_im(1);
read_im({1});
}
上面的i4
、i5
、i6
以及后面的read_im
的调用都是隐式转换,以i5
为例,能够将整数1
转换成Im(1)
。
使用explicit
关键字修饰类的构造函数,禁止隐式类型转换后,在进行类型转换时必须显式地指定转换操作。
struct Ex {
explicit Ex();
explicit Ex(int);
};
void read_ex(const Ex&);
int main(int argc, char const *argv[]) {
Ex e1;
Ex e2 = Ex();
Ex e3 = Ex(1);
Ex e4 = 1; // error
read_ex(Ex());
read_ex(Ex(1));
read_ex(1); // error
}
隐式转换问题
隐式转换虽然看起来比较便利,但降低了代码的可读性。并且,在一些情况下,这种转换会导致意外的结果,造成代码错误。
精度丢失
当将一个高精度的数据类型转换为低精度的类型时,可能会导致数据精度的丢失,还是以上面Im
数据结构为例。
struct Im {
Im();
Im(int);
};
// 将浮点数 1.6 赋值给了 i, 丢失了小数点后的精度
Im i = 1.6;
调用目标函数混乱
假设项目中有这样一段代码
class Book {
std::string title_;
std::string author_;
public:
Book(std::string t, std::string a) :
title_(t), author_(a) {};
};
void add_to_library(const Book&) {
std::cout