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

Gur*_*ami 55 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;
}
Run Code Online (Sandbox Code Playgroud)

YSC*_*YSC 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;
}
Run Code Online (Sandbox Code Playgroud)

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

  • @Nzall我已经编程40多年了,我精通大约六种语言,并且熟悉更多语言。就复杂性而言,现代C ++似乎本身就属于同类(我记得Ada刚问世时就曾对Ada进行过类似的思考,但C ++远远超过了它)。但是我想这证明了它的流行-如果没有人关心,他们不会继续增加它。 (8认同)
  • @Nzall您是否建议在新项目中不使用C?还是这不是一种高级语言? (7认同)
  • @Alexander C ++是最古老的高级语言之一,仍然在新项目中得到积极使用。较旧且仍在积极使用AFAIK的语言是FORTRAN,COBOL和LISP。结果是C ++比Java或C#等较年轻的语言具有更大的灵活性,但是这种灵活性的代价是更容易搞砸。 (5认同)
  • @Alexander _“默认情况下的隐式转换对我来说听起来很疯狂” _对所有C ++开发人员来说都听起来很疯狂。但是,这样做的选择早已做出,我们现在都为此付出了代价。 (4认同)
  • @Barmar非常字面上; 模板语法*本身*是图灵完备的。C ++ * parser *受制于停顿问题。 (4认同)

Nat*_*ica 30

实现此目的的方法是提供另一个匹配更好的构造函数,然后再构造delete一个错误。对于您的班级,添加

template <typename T>
A(T) = delete;
Run Code Online (Sandbox Code Playgroud)

将阻止从任何非 int


小智 8

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

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

A a{5}; // ok
A b{1.123}; // compile error
Run Code Online (Sandbox Code Playgroud)

证明


bra*_*o23 6

I just want to add that the A(double) = delete is a C++11 addition.

If for whatever reason you cannot use this relatively new construct, you can simply declare it as private as this:

class A{
  public:
    A(int);
  private:
    A(double);
}
Run Code Online (Sandbox Code Playgroud)


Ria*_*iaD 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;
}
Run Code Online (Sandbox Code Playgroud)

编译器资源管理器


Som*_*ken 4

显式删除构造函数double(可能添加float):

A(double) = delete;
Run Code Online (Sandbox Code Playgroud)