【问题标题】:How does const modifier for member functions affect overload resolution?成员函数的 const 修饰符如何影响重载决议?
【发布时间】:2015-01-15 21:01:38
【问题描述】:

我有以下测试代码:

#include <string>
#include <iostream>

class CString
{
public:
    CString(char const*) {}
};

class TestBed
{
public:
    void Comparison(CString const&) { std::cout << "CString Overload" << std::endl; }
    void Comparison(std::string const&) { std::cout << "std::string overload" << std::endl; }
};

int main()
{
    TestBed tb;
    tb.Comparison("Hello World");
}

此代码无法编译,因为对 Comparison() 的调用不明确。我期待这种行为。

但是,当我使 Comparison() 重载 const 中的任何一个时,例如:void Comparison(std::string const&amp;) constvoid Comparison(CString const&amp;) const(但不是两者),代码将编译并选择非常量重载。

重载解决规则非常复杂,我还没有看到任何描述const 如何影响这种情况的内容。我的理解是:

  1. 首先选择具有完全匹配参数的函数
  2. 接下来尝试一级隐式转换

在这两种情况下,1 和 2 都是模棱两可的。有人可以解释一下吗?谢谢。

【问题讨论】:

  • this指针也是一个(隐藏的)参数,进入解析。具有最少隐式转换的原型获胜,其中非 const 到 const 是一种转换。
  • @Creris 函数的 const 版本需要 2 次转换(1 次用于字符串,1 次用于 this),非 const 只需 1 次。
  • @MarkRansom 不抱歉,我以为他添加了新的重载,实际上他编辑了其中一个,所以转换为 1, 1 -> 2, 1 转换。
  • const 版本意味着两种转换:字符串文字 -> 字符串对象和TestBed&amp; -> const TestBed&amp;(对于*this)。非常量版本只有第一个转换(字符串),没有第二个。

标签: c++ c++11 overloading


【解决方案1】:

对于类方法,this 部分被认为是一个额外的参数。因此,如果您将 CString 设为一个 const,则会设置重载:

Comparison(const TestBed&, CString const&) // (1)
Comparison(TestBed&, std::string const&)   // (2)

对于(1),我们需要进行两次转换:const 转换,以及到CString 的转换。但是对于(2),我们只需要进行一次转换:到std::string。因此,(2) 是首选。

我们可以通过添加第三个函数来验证这一点,该函数对this 进行一次转换:

Comparison(const TestBed&, const char*)  // (3)

在这里,我们再次只有一次转换(在“第一个”参数中),因此重载集是不明确的。


在 [over.match.funcs] 中:

一个成员函数被认为有一个额外的参数,称为隐式对象参数,它 表示已为其调用成员函数的对象。出于重载决议的目的,静态和非静态成员函数都具有隐式对象参数,但构造函数没有。

对于非静态成员函数,隐含对象参数的类型为

—“对 cv X 的左值引用”,用于声明没有 ref-qualifier 或 & ref-qualifier 的函数

—“对 cv X 的右值引用”,用于使用 && ref-qualifier 声明的函数

其中 X 是函数所属的类,cv 是该成员的 cv 限定 函数声明。 [ 示例:对于类 X 的 const 成员函数,额外的参数假定为 具有类型“对 const X 的引用”。 ——结束示例]

在重载决议期间,隐含的对象参数与​​其他参数没有区别。

这就是我们考虑const TestBed&amp;TestBed&amp; 的原因。然后只需比较重载(1)(2) 之间的转换序列即可。对于第二个参数,两个转换序列是相等的,但对于第一个参数,(2) 具有更好的转换序列(即精确)——这就是它毫无歧义地获胜的原因。

【讨论】:

  • 我很想像您一样将我的评论扩展为完整的答案,但我认为一个好的答案需要参考标准。
  • @MarkRansom 试过了。很难从过载分辨率中找到一小部分来适应答案。
  • 干得好。我从来没有想过 static 函数也需要引用对象的常量这一事实,即使 this 不再是参数。
  • 绑定到const TestBed&amp;TestBed&amp; 具有完全匹配排名。两者都不涉及转换。相反,[over.ics.rank]/p3,项目符号 3.1.6 中的决胜局使 TestBed&amp; 变得更好。
  • @MarkRansom 为什么静态方法需要检查常量?它们不能通过 const AFAIK 重载,所以我不明白这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
  • 2021-11-29
相关资源
最近更新 更多