我认为在重载期间,编译器会检查形式参数是否属于同一类型。例如:
void a(int x)
void a(double x)
可能只是因为两个“x”具有差异类型而过载。
但是,以下两种类型有不同的类型吗?
void f(int y)
void f(int& y)
据我所知,一个是PBV而另一个是PBR。但第二个y的类型是“int”也是对的吗?为什么编译成功?
P.S。 我注意到虽然它编译,但它没有运行,报告模糊性的运行时错误。
答案 0 :(得分:8)
从广义上讲,功能可以在以下基础上重载:
该示例编译因为它满足第二个标准
int
和int &
是不同的数据类型。
考虑以下示例:
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
return 0;
}
上面的代码编译,因为它是有效的代码。根据传递给函数的函数参数,编译器可能/可能不会检测函数调用的最佳匹配。因此,允许函数本身共存,但它们在某些方面的使用可能会导致编译器模糊不清。
例如: 在下面的代码中,文字不能绑定到非const引用,因此函数调用的唯一候选者是非引用版本,这应该编译并正常工作:
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
foo(20);
return 0;
}
但是,
void foo(int i);
void foo(int& i);
void foo(int i){}
void foo(int& i){}
int main()
{
int i = 10;
foo(i);
return 0;
}
以上情况会导致编译器产生歧义,因为编译器无法检测到两个函数调用之间的最佳匹配。
答案 1 :(得分:2)
这取决于。如果不从代码中调用这些函数,编译器可能会优化它们。如果没有,您可以使用文本查看器打开.obj文件并搜索函数名称(给它一个比f
更独特的名称,例如floop
:-)),您将使用基本函数名称查看两个受损的名称。
但如果您尝试使用它们,那么您会注意到不同之处。如果你打电话
f(5);
编译器只能使用f(int y)
版本,因为通过引用传递常量是不可能的。但如果你这样做
int b = 10;
f(b);
然后编译器将发出一个amibuity错误,因为这两种f
形式都可以这样调用。
答案 2 :(得分:2)
让我们调用f(x),其中x是一个int。
$ 13.3.3.1.4 - “当参考类型的参数直接绑定时 (8.5.3)到一个参数表达式,隐式转换序列是 身份转换,除非参数表达式具有类型 这是参数类型的派生类,在这种情况下是 隐式转换序列是派生到基础的转换“
因此f(int&)是完全匹配,因此f(int)都是标识转换。因此含糊不清
现在让我们来电话'f(2)'
这很好,因为'f(int&)'根本不匹配,因为rvalues不绑定到非const lvalues。因此,没有歧义
因此,该标准允许'f(T)'abd'f(T&)'形成一个过载集。
答案 3 :(得分:1)
首先,总是在编译时报告模糊性。
其次,您的示例是否编译取决于您使用此函数的方式
void f(int y)
{
}
void f(int& y)
{
}
int main ()
{
int a = 10;
f (a); // ERROR: ambiguous call
f (10); // OK
}
在第一种情况下会出现错误,因为a
可以作为副本和引用传递。
在第二种情况下,没有错误,因为int
文字不能通过非const引用传递