避免构造函数中的隐式转换。 '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】:你可以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
【讨论】:
@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' 关键字在这里没有帮助的主要内容,如果未能解决你的问题,请参考以下文章