【问题标题】:Ambiguous overload with array passed as pointer数组作为指针传递的模棱两可的重载
【发布时间】:2015-09-11 11:43:34
【问题描述】:

以下代码

#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);
}

编译正常并按预期打印“B”。

但是当我将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 函数中访问它们,您就会遇到问题,正如 here 所解释的那样,因为foo(B*) 函数无法知道它实际上是在处理可能占用更多内存空间的C 对象。所以不要这样做!

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

【问题讨论】:

  • 在 vs2008 上,我无法重现错误 - 后一个测试用例打印“B”。
  • foo(&c[0]) 有效吗?
  • Arrays are not pointers。无论如何,这个想法是从哪里来的?此外,当您将C 的数组转换为指向B(或A,就此而言)的指针时,您需要进行数组访问的指针算法将无法解决;一旦C 包含一些数据成员,b[1] 将不会给你一个有效的对象,因为sizeof(B) != sizeof(C)(在此之前它也是未定义的行为)。
  • 在 foo(B*) 中,你可以通过 dynamic_cast 知道它是否是一个 C。 C* c = dynamic_cast(b) in foo(B* b) 并检查 c 是否为 nullptr(或 NULL für c++0x)。如果不是nullptr,就是C。
  • @Gombat 这些类不是多态的,不能使用dynamic_cast

标签: c++ arrays pointers overloading


【解决方案1】:

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

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

标准转换序列是按以下顺序进行的标准转换序列:
— 从以下集合中进行零次或一次转换:左值到右值转换,数组到指针转换, 以及函数到指针的转换。
— 从以下集合中进行零次或一次转换:积分提升、浮点提升、积分 转换、浮点转换、浮点整数转换、指针转换、指向 成员转换和布尔转换。

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

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

具有相同等级的两个转换序列 除非适用以下规则之一,否则无法区分:
— 如果 B 类直接或间接派生自 A 类,而 C 类直接或间接派生自 乙,
C* 到 B* 的转换优于 C* 到 A* 的转换

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

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • @sehe 我对这个问题与转换的关系比它的C[10] 不是真正的多态类型感到困惑?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-23
    • 2011-08-01
    • 2015-01-12
    • 1970-01-01
    相关资源
    最近更新 更多