C++ 显示关键字

    • explicit 修饰构造函数时,可以防止隐式转换和复制初始化
    • explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外
    1. struct A
    2. {
    3. A(int) { }
    4. operator bool() const { return true; }
    5. };
    6. struct B
    7. {
    8. explicit B(int) {}
    9. explicit operator bool() const { return true; }
    10. };
    11. void doA(A a) {}
    12. void doB(B b) {}
    13. int main()
    14. {
    15. A a1(1); // OK:直接初始化
    16. A a2 = 1; // OK:复制初始化
    17. A a3{ 1 }; // OK:直接列表初始化
    18. A a4 = { 1 }; // OK:复制列表初始化
    19. A a5 = (A)1; // OK:允许 static_cast 的显式转换
    20. doA(1); // OK:允许从 int 到 A 的隐式转换
    21. if (a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
    22. bool a6(a1); // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
    23. bool a7 = a1; // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换
    24. bool a8 = static_cast<bool>(a1); // OK :static_cast 进行直接初始化
    25. B b1(1); // OK:直接初始化
    26. B b2 = 1; // 错误:被 explicit 修饰构造函数的对象不可以复制初始化
    27. B b3{ 1 }; // OK:直接列表初始化
    28. B b4 = { 1 }; // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化
    29. B b5 = (B)1; // OK:允许 static_cast 的显式转换
    30. doB(1); // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换
    31. if (b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
    32. bool b6(b1); // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换
    33. bool b7 = b1; // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换
    34. bool b8 = static_cast<bool>(b1); // OK:static_cast 进行直接初始化
    35. return 0;
    36. }

    通过explicit来防止隐式转换

    #include <iostream>  
    
    struct TestClass {   
      template<typename T>
      TestClass(const T &t) {       
        std::cout << "Constructed a TestClass " << t << std::endl;     
      } 
    };
    
    void TakeATestClass(const TestClass &t) { }  
    
    int main() {   
      TakeATestClass("Bob"); 
    }
    

    对于上面的例子,尽管最终可能会通过编译器的编译,但是按照C++的原则“避免提供隐式转换”,对原有的类进行如下的修改可以防止隐式的转换。

    struct TestClass {   
      template<typename T>     
      explicit TestClass(const T &t) {       
        std::cout << "Constructed a TestClass " << t << std::endl;     
      } 
    };