c++ explicit关键字
c++ explicit关键字常见的应用场景是类的构造,用于修饰类的构造函数。假如有如下的一个类:
class Cube { private: double side; public: Cube(double aSide) :side{ aSide } {//constructor std::cout << "Cube constructor called" << "\n"; }; double volume() {//Caculate volume of a cube return side * side * side; }; bool hasLargerVolumeThan(Cube aCube) {//Compare volume of a cube with another return volume() > aCube.volume(); }; };
运行如下的代码:
int main(){ Cube box1{ 7.0 }; Cube box2{ 3.0 }; if (box1.hasLargerVolumeThan(box2)) { std::cout << "box1 is larger than box2." << "\n"; } else { std::cout << "Volume of box1 is less than or equal to that of box2." << "\n"; } std::cout << "volume of box1 is " << box1.volume() << "\n"; if (box1.hasLargerVolumeThan(50.0)) { std::cout << "Volume of box1 is greater than 50" << "\n"; } else { std::cout << "Volume of box1 is less than or equal to 50" << "\n"; } std::cout << "Volume of box1 is less than or equal to 50" << "\n"; return 0; }
运行结果为:
将class以UML表示出来:
当调用Cube类的hasLargerVolumeThan()函数时,参数aCube的类型是Cube,照理来说是只能对比两个Cube类型的 “Volume()” 的大小。但是从第二次对比行为来看,传入的参数是浮点型的 50.0 而不是一个Cube型的变量,类型对不上理应是报错,但实际上没有报错,通过了编译。这是因为将浮点型的传入参数隐式转换成了Cube类型,在转换的过程中,需要构造一个Cube类型的对象,所以会调用Cube类的构造函数,而传入的浮点型参数成为了构造函数的传入参数,用于构造一个新的Cube类型的对象。新构造的Cube类型的对象中,参数 “side” 为 50.0,则其 “Volume” 便为 50.0*50.0*50.0=125000.0 ,所以box1的 “Volume” 343 是小于等于125000.0的。
而explicit关键字的作用就是不再允许这种转换行为,只允许参数类型能够符合的情况。比如:
explicit Cube(double aSide) :side{ aSide } {//constructor std::cout << "Cube constructor called" << "\n"; };
修改后可以发现原来的不报错的函数报错,不再能通过编译:
参考资料
[1] Beginning C++17,5th Edition . Lvor Horton . Peter Van Weert . chapter 11.4.7