C++ C++;:使用显式关键字的编译错误
以下代码引发编译错误:C++ C++;:使用显式关键字的编译错误,c++,overloading,explicit,explicit-conversion,C++,Overloading,Explicit,Explicit Conversion,以下代码引发编译错误: #include <stdio.h> class Option { Option() { printf("Option()\n"); }; public: explicit Option(const Option& other) { printf("Option(const)\n"); *this = other; } explicit Option(Option& o
#include <stdio.h>
class Option
{
Option() { printf("Option()\n"); };
public:
explicit Option(const Option& other)
{
printf("Option(const)\n");
*this = other;
}
explicit Option(Option& other)
{
printf("Option(non-const)\n");
*this = other;
}
explicit Option(const int&)
{
printf("Option(value)\n");
}
};
void foo(Option someval) {};
int main()
{
int val = 1;
Option x(val);
foo(x);
}
如果我从explicit选项(const Option&other)
有人能给我解释一下编译错误的原因吗?
此外,如果调用foo(x)
中的显式选项(const Option&other)
和显式选项(Option&other)
?之间存在差异,则必须创建一个新的选项
,该选项将在执行foo
主体时变为someVal
。也就是说,x
需要复制到someVal
。编译器基本上尝试初始化选项someVal(x)
(首先尝试选项(Option&)
,然后尝试选项(Option const&)
),但它不能,因为您说过这两个构造函数都是显式的,不应该隐式调用。使用C++17,您可以显式插入缺少的构造函数调用以使其工作:foo(选项(x))
。在C++17之前,不可能调用foo
,因为编译器会不断尝试将对构造函数的调用插入到选项
,但没有可供插入的调用
在标准语言中,像foo(x)
这样的函数调用调用从x
复制初始化参数someVal
。复制从某个类的对象或派生类初始化该类的对象时,只考虑该目标类的转换构造函数。“转换构造函数”只是“非显式的构造函数”的一个花哨名称。然后通过正常重载解析选择其中最好的构造函数。因为没有一个构造函数不是显式的,所以在C++17之前,foo
是不可调用的。从C++17开始,当参数是prvalue时(如foo(选项(x))
),调用构造函数的要求可以回避,并且foo
可以调用
关于你的补充问题:
另外,如果显式选项(常量选项和其他)
和显式选项(选项和其他)
之间存在差异
当然:第一个承诺不会修改其论点,第二个则不会。您已经知道,可以将它们定义为执行不同的操作,重载解析将根据上下文选择其中一个:
Option x(1);
Option const y(2);
Option a(x); // calls Option(Option&) if available, which may modify x; calls Option(Option const&) if not, which shouldn't modify x
Option b(y); // must call Option(Option const&) because that promises not to modify y; cannot call Option(Option&) because it may modify y
通常会看到
显式
构造函数来防止不必要的隐式转换,但是显式
复制构造函数非常奇怪。因为显式关键字是一个很好的描述。在这种特殊情况下,explicit关键字可防止在调用foo函数时复制x。是关于何时使用显式构造函数的一个很好的讨论。两个复制ctor之间的区别在于,对于非常量版本,不能复制常量对象。一般来说,复制构造函数的const版本就足够了,您不必同时指定它们代码>,什么是*此=其他代码>应该调用?@TEDLYNMO它调用@Jánosbenjaminatal没有-它被隐式删除,因为有一个用户定义的复制构造函数。在C++17中,可能是因为新的复制省略规则或其他原因?如果是其他功能,请命名该功能?我很惊讶它能与C++17一起工作。@Jánosbenjaminatal是的,它是复制省略。
Option x(1);
Option const y(2);
Option a(x); // calls Option(Option&) if available, which may modify x; calls Option(Option const&) if not, which shouldn't modify x
Option b(y); // must call Option(Option const&) because that promises not to modify y; cannot call Option(Option&) because it may modify y