Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:使用显式关键字的编译错误_C++_Overloading_Explicit_Explicit Conversion - Fatal编程技术网

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