为什么 'explicit' 关键字允许隐式转化?

Why is the 'explicit' keyword allowing implicit conversions?

本文关键字:许隐式 关键字 explicit 为什么      更新时间:2023-10-16
class Test {
    private:
    int value;
    public:
    void display(void)
    {
        cout << "Value [" << value << "]" << endl;
    }
    explicit Test(int i)
    {
        value=i;
    }   
};
int main() {
    Test a(5);
    Test b(4.9);
    a.display();
    b.display();
    cin.get();
    return 0;
}

浮点值被转换为 int,即使提到了显式。

我期望(错误地(浮点数不会转换为整数并且对象 b 不会被构造。

explicit指的是构造函数本身,而不是构造函数的参数。 显式构造函数不能用作类型Test隐式转换。

void function( Test param );
function( 5 ); // Your "explicit" makes this call an error.
               // The parameter must be explicitly cast, such as Test(5)

在 C++11 或更高版本中,可以使用模板参数的= delete语法来阻止隐式参数转换。

  Test(int i)
  {
      value=i;
  }   
  template<typename T>
  Test(const T&) = delete;
  // ^ Aside from your int constructor and the implicitly-generated 
  // copy and move constructors, this will be a better match for any other type

在 C++20 或更高版本中,可以使用 std::same_as 概念阻止隐式参数转换。

  Test(std::same_as<int> auto i)
  {
      value=i;
  }   

explicit只是阻止任何隐式转换。因此,如果您有:

void foo(Test t);

不能调用foo(4);,因为Test构造函数是 explicit 。你必须打电话给foo(Test(4));.explicit关键字与施工期间可能必须发生的任何转换无关。

从标准 [class.conv.ctor]:

显式构造

函数像非显式构造函数一样构造对象,但仅在 直接初始化语法 (8.5( 或显式使用强制转换(5.2.9、5.4(的位置。

这意味着Test t = 4;也是非法的,但Test t(42.0)很好。

这是一个

浮动积分转换.
也就是说:它是类型double的prvalue到类型signed int的prvalue之间的隐式转换。它丢弃小数部分。

TL;DR:转换发生在"double"和"int"之间,而不是在你的Test构造函数中。如果要防止使用 floatdouble 调用该构造函数,可以添加定义:

Test(double) = delete;

在你的Test课上。 在编译器资源管理器上直播