Pie*_*yts 1 c++ arrays pointers overloading
以下代码
#include <iostream>
using namespace std;
class A {};
class B : public A {};
class C : public B {};
void foo(A *a) {
cout << 'A' << endl;
}
void foo(B *b) {
cout << 'B' << endl;
}
int main() {
C *c = new C[10];
foo(c);
}
Run Code Online (Sandbox Code Playgroud)
编译好并按预期打印'B'.
但是当我改变main()功能时
int main() {
C c[10];
foo(c);
}
Run Code Online (Sandbox Code Playgroud)
我收到编译错误说
test_arr.cpp: In function 'int main()':
test_arr.cpp:23:10: error: call of overloaded 'foo(C [10])' is ambiguous
test_arr.cpp:23:10: note: candidates are:
test_arr.cpp:11:6: note: void foo(A*)
test_arr.cpp:15:6: note: void foo(B*)
Run Code Online (Sandbox Code Playgroud)
为什么现在模棱两可?我以为数组总是只是一个指针,所以我并没有真正看到它的区别.
编辑:
我才意识到整个代码我张贴是一个坏主意,开始用:只要你的数据成员添加到类和访问他们在foo你遇到问题的功能,如解释在这里,因为foo(B*)函数没有办法知道它实际上处理C可能占用更多内存空间的对象.所以不要这样做!
尽管如此,我仍然有兴趣了解为什么编译器抱怨模棱两可,因为我实在看不出有问题的是在这里.
我相信这是一个gcc bug.代码编译在clang上.
首先,两位候选人都是可行的.来自[conv]:
甲标准转换序列是标准转换的以下顺序的序列:
-零或者选自以下组的一个转换:左值到右值转换,阵列到指针转换,和功能到指针转换.
- 来自以下集合的零或一次转换:整数促销,浮点促销,积分转换,浮点转换,浮点积分转换,指针转换,成员转换指针和布尔转换.
两次调用foo都涉及到数组到指针的转换(从C[10]到C*),然后是指针转换(从C*到A*或来自B*).这是允许的标准转换.
现在,我们如何对这些转换进行排名?有趣的是,标准中的行恰好与我们的用例匹配,在[over.ics.rank]中:
具有相同的秩两个转换序列是无法区分的,除非下列规则之一适用:
-如果类B从类A直接或间接衍生和类C是直接或间接地从B来源,
- C*的转换为B*是更好比C*转换为A*
我们有两个相同等级(转换)的转换序列,它们都是可行的,但一个被认为比另一个更好.该代码应明确地喜欢foo(B* )过foo(A* ).c声明为数组的事实不应该使它模糊不清.