为什么在类的const版本中选择非const版本?

iam*_*ind 6 c++ overloading const overload-resolution

以下是测试代码:

struct A
{
  operator int ();
  operator int () const;
};

void foo (const int);
Run Code Online (Sandbox Code Playgroud)

现在,在调用时:

foo(A());  // calls A::operator int()
Run Code Online (Sandbox Code Playgroud)

为什么总是选择非const版本?即使制作operator const int () const;对调用也没有任何影响foo().除了标准参考,有人可以逻辑解释,背后的原因是什么?

Jam*_*lis 13

A()为您提供一个A非const限定的临时对象.该A()表达式是一个右值表达式,是的,但是这并不能使A对象const限定.

由于A对象不是const限定的,因此非const operator int()是精确匹配,const operator int()需要限定转换,因此选择非const重载作为最佳匹配.

如果你想要它是const限定的,你需要显式请求一个const限定的A:

foo(identity<const A>::type());
Run Code Online (Sandbox Code Playgroud)

在哪里identity定义为

template <typename T>
struct identity { typedef T type; };
Run Code Online (Sandbox Code Playgroud)

注意,operator const int() const和之间确实没有区别operator int() const:结果是rvalue,只有class-type rvalues可以是const限定的(int不是类类型).

另请注意void foo(const int),您和之间没有区别void foo(int).参数类型的顶级const限定符不会影响函数的类型(即,这两个声明的类型都是void foo(int)).除其他原因外,这是因为调用者是否存在顶级const限定符并不重要; 无论如何都必须制作副本.顶级const限定符仅影响函数的定义.

  • 就调用者而言,`foo(const int)`和`foo(int)`是相同的.函数参数的顶级const限定符不是函数类型的一部分.(您可以这样考虑它:调用者并不关心是否存在顶级const限定符;它并不重要,因为它只需要知道将要创建一个副本.) (2认同)

Che*_*Alf 5

James McNellis的回答确实涵盖了这一切,但它并没有伤害(我希望)更多的解释.

所以.

你打电话的时候 …

    o.operator int()
Run Code Online (Sandbox Code Playgroud)

...然后过载选择完全取决于.的常数o.

没有其他的.

要了解原因,请考虑以下类:

struct Bar
{
    void f() {}
    void f() const {}
};
Run Code Online (Sandbox Code Playgroud)

从技术上讲,这些成员函数不需要是成员函数.他们也可以被选为独立的职能.但他们需要Bar争论:

struct Bar
{};

void f( Bar& ) {}
void f( Bar const& ) {}
Run Code Online (Sandbox Code Playgroud)

希望现在你可以更容易地看到它

Bar o;
f( o );
Run Code Online (Sandbox Code Playgroud)

然后可以选择第一个功能.就是这样.因为如果选择了第二个函数,那么你永远不会得到第一个函数.因为如果你制作了这个对象const,那么它就会破坏const正确性以选择第一个.因此,当对象const只能选择第二个时,因此,当它不是const第一个被选中时.

简而言之,这个规则的唯一实际替代方案是始终选择第二个,这将使第一个相当无用,是吗?

干杯&hth.,