4

我有一个关于 c++ 函数匹配类型参数Tconst T&. 假设我有以下两个功能:

void f(int i) {}
void f(const int &ri) {}

如果我f用类型的参数调用,const int那么这个调用当然是模棱两可的。但是为什么f带有类型参数的调用int也是模棱两可的呢?不会是第一个版本f的完全匹配,而第二个版本的匹配更差,因为int参数必须转换为const int?

const int ci = 0;
int i = 0;
f(ci); // of course ambiguous
f(i); // why also ambiguous?

我知道这种重载没有多大意义,因为调用 off几乎总是模棱两可的,除非参数类型 T 没有可访问的复制构造函数。但我只是在研究函数匹配的规则。

问候,凯文

编辑:为了让我的问题更清楚。如果我有两个功能:

void f(int *pi) {}
void f(const int *pi) {}

那么下面的调用就没有歧义了:

int i = 0;
f(&i); // not ambiguous, first version f(int*) chosen

尽管选择了第一个版本的两个版本f都可以调用&i,因为第二个版本f将包含一个转换,const.也就是说,第一个版本是“更好的匹配”。但是在这两个函数中:

void f(int i) {} and
void f(const int &ri) {}

由于某种原因,这种额外的转换const似乎被忽略了。同样,这两个版本f都可以用int. 但同样,第二个版本f需要进行转换,const这将使其比第一个版本更差f(int).

int i = 1;
// f(int) requires no conversion
// f(const int &) does require a const conversion
// so why are both versions treated as "equally good" matches?
// isnt this analogous to the f(int*) and f(const int*) example?
f(i); // why ambiguous this time?
4

3 回答 3

4

一个调用涉及“左值到右值转换”,另一个调用需要身份转换(对于引用)或“限定调整”(对于指针),并且根据标准,在重载解析时这些都被平等对待。

在此处输入图像描述

因此,基于不同的转换,两者都不是更好。

但是,标准第 13.3.3.2 节中有一条特殊规则,该规则仅适用于被比较的两个候选者通过引用获取参数的情况。

标准转换序列S1是比标准转换序列更好的转换序列S2if ... S1andS2是引用绑定 (8.5.3),并且引用所指的类型是相同的类型,除了顶级cv-qualifiers和类型由引用初始化的引用比由引用初始化的S2引用更具有cv 限定S1

指针有一个相同的规则。

因此编译器会更喜欢

f(int*);
f(int&);

超过

f(const int*);
f(const int&);

f(int)分别,但是vs f(const int)vs没有偏好f(const int&),因为左值到右值的转换和资格调整都被认为是“精确匹配”。


同样相关,来自第 13.3.3.1.4 节:

当引用类型的参数直接绑定到参数表达式时,隐式转换序列是恒等转换,除非参数表达式的类型是参数类型的派生类,在这种情况下,隐式转换序列是派生的-基数转换。

于 2013-08-23T20:44:46.990 回答
1

第二个调用f(i)也是模棱两可的,因为void f(const int &ri)表明它ri是一个引用i并且是一个常量。这意味着它表示它不会修改 i传递给该函数的原始文件。

是否修改传递的参数的选择权在函数的实现者手中,而不是在使用该函数的客户端程序员手中。

于 2013-08-23T18:33:18.880 回答
0

第二次调用 f(i) 不明确的原因是因为对于编译器来说,这两个函数都是可以接受的。const-ness 不能用于重载函数,因为可以在一个原因中使用不同的 const 版本的函数。所以在你的例子中:

int i = 0;
fi(i);

编译器如何知道您打算调用哪个函数?const 限定符仅与函数定义相关。

有关更详细的说明,请参阅const 函数重载。

于 2013-08-23T19:30:36.620 回答