数组的模糊重载作为指针传递

时间:2015-09-11 11:43:34

标签: 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);
}

编辑精美并打印&#39; B&#39;如预期的那样。

但是当我将main()功能更改为

int main() {
    C c[10];

    foo(c);
}

我收到编译错误

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*)

为什么现在模棱两可?我认为阵列总是只是一个指针,所以我不能真正看到差异。

修改:

我刚刚意识到我发布的所有代码都是一个坏主意:只要您将数据成员添加到类中并在foo函数中访问它们,就会遇到问题,如{{ 3}},因为foo(B*)函数无法知道它实际上正在处理可能需要更多内存空间的C个对象。所以不要这样做!

尽管如此,我仍然有兴趣理解为什么编译器会在这里抱怨歧义,因为我真的没有在这里看到 的问题。

2 个答案:

答案 0 :(得分:5)

我相信这是一个gcc bug。代码编译在clang上。

首先,两位候选人都是可行的。来自[conv]:

  

标准转换序列是一系列标准转换,顺序如下:
   - 来自以下集合的零或一次转换:左值到右值转换,数组到指针转换,   和功能到指针的转换    - 来自以下集合的零或一次转换:整数促销,浮点促销,积分   转换,浮点转换,浮点积分转换,指针转换,指针指向   成员转换和布尔转换。

foo的两次调用都涉及数组到指针的转换(从C[10]C*),然后是指针转换(从C*A* 1}}或B*)。这是允许的标准转换。

现在,我们如何对这些转化进行排名?有趣的是,标准中的行匹配完全我们的用例,在[over.ics.rank]中:

  

具有相同等级的两个转换序列   除非符合以下规则之一,否则无法区分:
   - 如果B类直接或间接地从A类派生而C类是直接或间接派生的   B,
   - 将C *转换为B *优于将C *转换为A *

我们有两个相同等级(转换)的转换序列,它们都是可行的,但一个被认为比另一个更好。代码应明确地优先于foo(B* )而不是foo(A* )c被声明为数组的事实不应该使它变得模棱两可。

答案 1 :(得分:1)

C c[10]不是多态类型。您可能能够获得指向数组中第一个项目的指针,但这仍然只是C

如果您尝试将其强制转换为B,则会进行切片。

C* c = new C();可以是dynamic_castB