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

相关