C++:使用显式关键字的编译错误

标签 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& 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);
}

抛出的错误是:

main.cpp:31:10: error: no matching function for call to ‘Option::Option(Option&)’
     foo(x);
          ^
main.cpp:5:5: note: candidate: ‘Option::Option()’
     Option() { printf("Option()\n"); };
     ^~~~~~
main.cpp:5:5: note:   candidate expects 0 arguments, 1 provided
main.cpp:25:6: note:   initializing argument 1 of ‘void foo(Option)’
 void foo(Option someval) 

如果我从explicit Option(const Option& other)中删除explicit关键字,错误就会消失

谁能给我解释一下编译错误的原因是什么? 另外,显式选项(const Option& other)显式选项(Option& other)之间是否有区别?

最佳答案

通话中foo(x) ,一个新的Option必须创建,它将成为 someVal foo执行期间的 body 。即x需要复制到 someVal 。编译器本质上尝试初始化 Option someVal(x); (首先尝试 Option(Option&) ,然后 Option(Option const&) ),但它不能,因为你说这两个构造函数都是 explicit并且不应该被隐式调用。使用 C++17,您可以显式插入缺少的构造函数调用以使其正常工作:foo(Option(x)) 。在C++17之前,不可能调用foo ,因为编译器将继续尝试将对构造函数的调用插入 Option但没有一个可用于插入。

在标准语言中,函数调用如 foo(x)调用参数 someValx复制初始化 。从某个类或派生类的对象复制初始化该类的对象时,仅考虑该目标类的转换构造函数。 “转换构造函数”只是“不是 explicit 的构造函数”的一个奇特名称。然后通过正常的重载决策选择其中最好的构造函数。因为您的构造函数没有不是 explicit ,这总是失败并且 foo在 C++17 之前是不可调用的。从 C++17 开始,当参数是纯右值(如 foo(Option(x)) )时,可以回避调用构造函数的要求,并且 foo变得可调用。

对于你的附带问题:

Also, if there a difference between explicit Option(const Option& other) and explicit Option(Option& other)?

当然:第一个 promise 不会修改其参数,而第二个则不会。您已经知道它们可以被定义为执行不同的操作,并且重载解析将根据上下文优先选择其中之一:

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

关于C++:使用显式关键字的编译错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60895192/

相关文章:

c++ - 如何覆盖基类的 (->) 运算符的成员

java - 将执行哪个重载方法以及为什么?

c++ - 防止隐式转换但允许列表初始化?

c# - 我们什么时候必须在 C# 中使用隐式和显式运算符?

c++ - 使用 __typeof 弱自赋值的解释

c++ - boost::regex 和 std::regex 之间不一致?

c++ - 清理 VC++ 6 项目

c++ - 如何使用 Argv 编写基于范围的 For 循环?

c++ - 函数重载 C++ 指针

c++ - (涉及显式)运算符和构造函数转换的优先级