C++ 数组作为指针传递的不明确重载
下面的代码C++ 数组作为指针传递的不明确重载,c++,arrays,pointers,overloading,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 *
#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);
}
我得到一个编译器错误,说
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
函数中访问它们,您就会遇到问题,正如所解释的,因为foo(B*)
函数无法知道它实际上在处理可能占用更多内存空间的C
对象。所以不要这样做
尽管如此,我仍然有兴趣理解为什么编译器在这里抱怨歧义,因为我真的不认为这有什么问题。
C[10]
不是多态类型。您可能能够获得指向数组中第一项的指针,但这仍然只是一个C
如果您尝试将其强制转换为B
,则会得到切片
C*C=newc()代码>可以是动态的
到B
C[10]
不是多态类型。您可能能够获得指向数组中第一项的指针,但这仍然只是一个C
如果您尝试将其强制转换为B
,则会得到切片
C*C=newc()代码>可以是动态的
到B
我相信这是一个gcc错误。代码在叮当声中编译
首先,两位候选人都是可行的。从[conv]:
标准转换序列是按以下顺序进行的标准转换序列:
-以下集合的零或一个转换:左值到右值转换,数组到指针转换,
和函数到指针的转换。
-以下集合的零或一次转换:整数提升、浮点提升、整数
转换,浮点转换,浮点积分转换,指针转换,指针到
成员转换和布尔转换
对foo
的两个调用都涉及数组到指针的转换(从C[10]
到C*
),然后是指针转换(从C*
到a*
或B*
)。这是允许的标准转换
现在,我们如何对这些转换进行排序?有趣的是,标准中的行与我们的用例完全匹配,在[over.ics.rank]中:
具有相同秩的两个转换序列
除非下列规则之一适用,否则无法区分:
-如果B类直接或间接源自A类,C类直接或间接源自
B、
-将C*转换为B*比将C*转换为A*更好。
我们有两个相同等级(转换)的转换序列,它们都是可行的,但一个被认为比另一个更好。代码应该明确地选择foo(B*)
而不是foo(A*)
。c
被声明为数组这一事实不应使其模棱两可 我认为这是一个gcc错误。代码在叮当声中编译
首先,两位候选人都是可行的。从[conv]:
标准转换序列是按以下顺序进行的标准转换序列:
-以下集合的零或一个转换:左值到右值转换,数组到指针转换,
和函数到指针的转换。
-以下集合的零或一次转换:整数提升、浮点提升、整数
转换,浮点转换,浮点积分转换,指针转换,指针到
成员转换和布尔转换
对foo
的两个调用都涉及数组到指针的转换(从C[10]
到C*
),然后是指针转换(从C*
到a*
或B*
)。这是允许的标准转换
现在,我们如何对这些转换进行排序?有趣的是,标准中的行与我们的用例完全匹配,在[over.ics.rank]中:
具有相同秩的两个转换序列
除非下列规则之一适用,否则无法区分:
-如果B类直接或间接源自A类,C类直接或间接源自
B、
-将C*转换为B*比将C*转换为A*更好。
我们有两个相同等级(转换)的转换序列,它们都是可行的,但一个被认为比另一个更好。代码应该明确地选择foo(B*)
而不是foo(A*)
。c
被声明为数组这一事实不应使其模棱两可 在vs2008上,我无法重现错误-后一个测试用例打印“B”。foo(&c[0])是否有效?。不管怎么说,这个想法是从哪里来的?此外,当您将C
数组转换为指向B
(或A
)的指针时,数组访问所需的指针算法将无法实现;一旦C
包含一些数据成员,b[1]
将不会为您提供有效的对象,因为sizeof(b)!=sizeof(C)
(在此之前也是未定义的行为)。在foo(B*)中,您可以通过使用dynamic_cast知道它是否是C。C*C=foo(b*b)中的动态_cast(b),并检查C是否为NULL ptr(或NULL für C++0x)。如果不是nullptr,则为C。@Gombat这些类不是多态的,您不能使用dynamic\u cast
。在vs2008上,我无法重现错误-后一个测试用例打印“B”。foo(&C[0])有效吗?。不管怎么说,这个想法是从哪里来的?此外,当您将C
数组转换为指向Btest_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*)