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

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可能占用更多内存空间的对象.所以不要这样做!

尽管如此,我仍然有兴趣了解为什么编译器抱怨模棱两可,因为我实在看不出有问题的是在这里.

Bar*_*rry 5

我相信这是一个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声明为数组的事实不应该使它模糊不清.