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

Posted

技术标签:

【中文标题】避免构造函数中的隐式转换。 \'explicit\' 关键字在这里没有帮助【英文标题】:Avoiding implicit conversion in constructor. The 'explicit' keyword doesn't help here避免构造函数中的隐式转换。 'explicit' 关键字在这里没有帮助 【发布时间】:2019-07-31 15:00:09 【问题描述】:

我能够避免使用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;

【问题讨论】:

【参考方案1】:

你可以deleteA::A(&lt;anything not an int&gt;);:

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

【讨论】:

@Alexander C++ 是最古老的高级语言之一,仍然在新项目中得到积极使用。唯一较旧且仍在积极使用 AFAIK 的语言是 FORTRAN、COBOL 和 LISP。这样做的结果是,C++ 比 Java 或 C# 等年轻语言具有更大的灵活性,但这种灵活性的代价是更容易搞砸一些事情。 @Alexander “implicit-conversion-by-default 对我来说听起来很疯狂” 对于所有 C++ 开发人员来说,这听起来很疯狂。但是这样做的选择是很久以前的事了,我们现在都在付出代价。 @Nzall 你是说 C 在新项目中的使用不多吗?还是说它不是高级语言? @Nzall 我从事编程已有 40 多年了,我精通大约六种语言,并且熟悉更多语言。就复杂性而言,现代 C++ 本身似乎属于一个类(我记得 Ada 刚问世时也有类似的想法,但 C++ 远远超过了这一点)。但我想这证明了它的受欢迎程度——如果没有人关心,他们就不会继续添加它。 @Barmar 从字面上看;模板语法独立是图灵完备的。 C++ 解析器会遇到停止问题。【参考方案2】:

实现这一点的方法是提供另一个更匹配的构造函数,然后delete它,所以你会得到一个错误。对于您的班级,添加

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

将阻止类从不是 int 的任何东西构造出来

【讨论】:

【参考方案3】:

您可以通过使用大括号初始化来规避这个问题。例如:

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

A a5; // ok
A b1.123; // compile error

Proof

【讨论】:

【参考方案4】:

我只想补充一点,A(double) = delete 是一个 C++11 加法。

如果由于某种原因你不能使用这个相对较新的结构,你可以简单地将它声明为私有的:

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

【讨论】:

【参考方案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

【讨论】:

【参考方案6】:

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

A(double) = delete;

【讨论】:

【参考方案7】:

您应该使用 gcc 的 -Wconversion 标志,当将浮点数隐式转换为 int 时会产生警告。 添加 -Werror 以将此警告(实际上都是)转换为错误。

【讨论】:

以上是关于避免构造函数中的隐式转换。 'explicit' 关键字在这里没有帮助的主要内容,如果未能解决你的问题,请参考以下文章

explicit构造函数

C++关键字之:explicit

C++中的explicit关键字的用法

explicit作用:

explicit,violate,volatile,mutable小结

7. 类