避免在构造函数中进行隐式转换。 'explicit'关键字在这里没有帮助

时间:2019-07-31 15:00:09

标签: c++ c++11

我能够避免使用explicit关键字对构造函数进行隐式转换。因此,现在可以避免像A a1 = 10;这样的转化。

但是我仍然可以初始化A a1 = A(20.2);。如何禁用对象创建,以便仅在我们将整数作为参数传递时才能创建对象,例如A a1 = A(10)

#include <iostream>

class A
{
public:
    explicit A(int a)
    {
        num = a;
    }

    int num;
};

int main()
{
    A a1 = A(10.0);
    std::cout << a1.num;
    return 0;
}

7 个答案:

答案 0 :(得分:74)

您可以delete A::A(<anything not an int>);

struct A
{
    explicit A(int a)
    : num(a)
    {}

    template<class T>
    A(T) = delete;

    int num;
};

int main()
{
    //A a1=A(10.0); // error: use of deleted function 'A::A(T) [with T = double]'
    A a2 = A(10); // OK
    (void) a2;
}

演示:https://coliru.stacked-crooked.com/a/425afc19003697c9

答案 1 :(得分:30)

实现此目的的方法是提供另一个匹配更好的构造函数,然后delete进行匹配,这样您会得到一个错误。为您的班级添加

template <typename T>
A(T) = delete;

将阻止从非int

的任何内容构造类。

答案 2 :(得分:8)

您可以通过使用大括号初始化来解决此问题。例如:

struct A {
  A(int _a) : a(_a) {}
  int a;
};

A a{5}; // ok
A b{1.123}; // compile error

Proof

答案 3 :(得分:6)

我只想补充一下,A(double) = deleteC++11的补充。

如果出于某种原因您不能使用此相对较新的构造,则可以将其声明为私有:

class A{
  public:
    A(int);
  private:
    A(double);
}

答案 4 :(得分:5)

为了避免在各处int-> double转换,不仅限于您的情况。使用g ++,您可以使用-Wconversion -Werror。请注意,在您的特定情况下将允许使用该代码,因为编译器理解10.0是文字的,但是它将失败于以下情况的编译:

class A
{
public:
    explicit A(int a)
    {
        num = a;
    }

    int num;
};

int main()
{
    double x = 10;
    A a1 = A(x);
    static_cast<void>(a1);
    return 0;
}

Compiler explorer

答案 5 :(得分:4)

明确删除double的构造函数(可能添加float):

A(double) = delete;

答案 6 :(得分:4)

您应该使用gcc的-Wconversion标志,在将float隐式转换为int时将生成警告。 添加-Werror可以将此警告(实际上全部)转换为错误。