我有以下测试代码:
#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&) const
或void Comparison(CString const&) const
(但不是两者),代码编译并选择非-const overload。
重载解析规则非常复杂,我还没有看到任何描述const
如何影响这种情况的内容。我的理解是:
在这两种情况下,1&amp; 2是模棱两可的。有人可以解释一下吗?感谢。
答案 0 :(得分:7)
对于类方法,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]中:
成员函数被认为有一个额外的参数,称为隐式对象参数,其中 表示已调用成员函数的对象。出于重载解析的目的,静态和非静态成员函数都有一个隐式对象参数,但构造函数没有。
对于非静态成员函数,隐式对象参数的类型为
- 对于没有引用限定符或使用&amp;而声明的函数的“对cv X的左值引用” REF-限定符
对于用&amp;&amp ;;声明的函数,- “对cv X的rvalue引用” REF-限定符
其中X是函数所属的类,cv是成员的cv资格 功能声明。 [示例:对于类X的const成员函数,假设为额外参数 有类型“引用const X”。 - 例子]
在重载解析期间,隐含的对象参数与其他参数无法区分。
这确定了我们考虑const TestBed&
vs TestBed&
的原因。然后,只需比较重载(1)
和(2)
之间的转换序列。对于第二个参数,两个转换序列都相等,但对于第一个参数,(2)
具有更好的转换序列(即Exact) - 这就是为什么它在没有歧义的情况下获胜。