为什么选择非常量版本而不是类的常量版本



以下是测试代码:

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

现在,在调用时:

foo(A());  // calls A::operator int()

为什么它总是选择非常量版本?即使生成operator const int () const;也不会对调用foo()产生任何影响。除了标准参考之外,有人能合乎逻辑地解释它背后的原因吗?

A()为您提供了一个非常量限定的临时A对象。是的,A()表达式是一个右值表达式,但这不会使A对象常量限定。

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

如果您希望它是const限定的,您需要显式地请求一个const限定A:

foo(identity<const A>::type());

其中identity被定义为

template <typename T>
struct identity { typedef T type; };

注意,operator const int() constoperator int() const之间实际上没有区别:结果是一个右值,并且只有类类型的右值可以是const限定的(int不是类类型)。

还要注意,您拥有的void foo(const int)void foo(int)之间没有区别。参数类型上的顶级常量限定符不会影响函数的类型(即,这两个声明的类型都是void foo(int))。除其他原因外,这是因为是否存在顶级const限定符对调用者来说并不重要;不管怎样,它都必须复印一份。顶级const限定符只影响函数的定义。

James McNellis’答案确实涵盖了所有内容,但事实并非如此;(我希望)多做一些解释。

所以。

当您呼叫…

    o.operator int()

…则过载选择完全取决于CCD_ 18的常数。

没有别的。

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

struct Bar
{
    void f() {}
    void f() const {}
};

从技术上讲,这些成员职能不一定是成员职能。他们也可以被选为独立的职能部门。但他们需要Bar论点:

struct Bar
{};
void f( Bar& ) {}
void f( Bar const& ) {}

希望现在,当你进行时,更容易看到这一点

Bar o;
f( o );

则可以选择第一个函数。事实的确如此。因为如果选择了第二个函数,那么你就永远无法获得第一个。因为如果您将对象设为const,那么选择第一个对象将破坏const的正确性。因此,当对象是const时,只能选择第二个,因此,当不是const时,选择第一个。

简言之,这个规则的唯一实用替代方案是总是选择第二个,这会使第一个变得毫无用处,是吗?

干杯&hth。,

关于C++,您必须记住的一条规则是:它从不在选择重载时考虑返回的值。在这种情况下,由于operator int函数不接受参数,因此也不能使用参数列表来缩小选择范围。它所能使用的就是从中调用它的对象的常量。由于这是一个新的临时对象,它不是const,所以它不会选择const重载。

最新更新