为什么类的 const 版本选择非常量版本?

发布于 2024-11-17 10:04:26 字数 386 浏览 1 评论 0原文

以下是测试代码:

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

void foo (const int);

现在,调用时:

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

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

Following is the test code:

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

void foo (const int);

Now, upon invoking:

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

Why does it always chooses the non-const version ? Even making operator const int () const; doesn't have any effect on invoking foo(). Apart from standard reference, can someone explain logically, the reason behind it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

绝對不後悔。 2024-11-24 10:04:26

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

由于 A 对象不是 const 限定的,因此非 const operator int() 与 const 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) 之间没有区别。参数类型的顶级 const 限定符不会影响函数的类型(即,这两个声明的类型都是 void foo(int))。除其他原因外,这是因为对于调用者来说是否有顶级 const 限定符并不重要;无论如何,它都必须复制一份。顶级 const 限定符仅影响函数的定义。

A() gives you a temporary A object that is not const-qualified. The A() expression is an rvalue expression, yes, but that does not make the A object const-qualified.

Since the A object is not const-qualified, the non-const operator int() is an exact match and the const operator int() requires a qualification conversion, so the non-const overload is selected as the best match.

If you want it to be const-qualified, you'd need to explicitly request a const-qualified A:

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

where identity is defined as

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

Note that there is really no difference between operator const int() const and operator int() const: the result is an rvalue and only class-type rvalues can be const-qualified (int is not a class type).

Note also that there is no difference between the void foo(const int) that you have and void foo(int). Top-level const-qualifiers on parameter types do not affect the type of the function (i.e., the type of both of those declarations is void foo(int)). Among other reasons, this is because it doesn't matter to the caller whether there is a top-level const-qualifier; it has to make a copy regardless. The top-level const-qualifier affects only the definition of the function.

街道布景 2024-11-24 10:04:26

詹姆斯·麦克内利斯' 的答案确实涵盖了所有内容,但(我希望)更多解释也不会造成伤害。

所以。

当您调用……

    o.operator int()

时,重载选择完全取决于o的常量。

没有别的了。

要了解原因,请考虑此类:

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 时,将选择第一个。

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

干杯&呵呵,

James McNellis’ answer really covered it all, but it doesn’t hurt (I hope) with more explanations.

So.

When you call …

    o.operator int()

… then the overload selection depends entirely on the constness of o.

Nothing else.

To see why, consider this class:

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

Technically those member functions do not need to be member functions. They could just as well have been chosen to be free standing functions. But then they need Bar argument:

struct Bar
{};

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

And hopefully now it's easier to see that when you do

Bar o;
f( o );

then the first function can be selected. And so it is. Because if the second function was selected, then you could never get the first one. Because if you make the object const, then it would break const correctness to select the first one. So when the object is const only the second can be selected, hence, when it is not const the first one is selected.

In short, the only practical alternative to this rule would be to always select the second one, which would make the first one rather useless, yes?

Cheers & hth.,

白首有我共你 2024-11-24 10:04:26

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

One rule you have to remember about C++: it never takes into account the value that is being returned when it selects an overload. In this case since the operator int function takes no parameters, it can't use the parameter list to narrow down the choices either. All it can use it the constness of the object that it's being called from. Since this is a new temporary object, it's not const, so it doesn't choose the const overload.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文