如果B
是A
的子类。
我在main()
:
B** b = new B*[10];
... // some algorithm that does b[i] = new B(..);
所以我有一个指向对象B
的指针数组。
然后我有一个功能:
void f(A** foo);
如果在主要方面,我会这样做:f(b);
我会收到警告,但很明显,如果我这样做:f((A**)b);
,我就不会。
(A**)
它有点讨厌。我想知道在C ++中是否有更优雅的方式,至少将类型检查作为dynamic_cast
。
我希望foo对A类或子类的对象数组进行排序(仅使用交换)。所以制作一个通用的排序算法。我希望你现在能更好地理解我的问题。
答案 0 :(得分:2)
A**
和B**
是两种完全不同的类型。仅仅因为存在从B*
到A*
的隐式转换并不意味着从B**
到A**
存在相同的转换。有关详细信息,请参阅此常见问题解答Converting Derived* → Base* works OK; why doesn't Derived** → Base** work?
答案 1 :(得分:2)
如果您尝试隐式地将B**
强制转换为A**
,则会出现警告或错误:这样做是不安全的。
将数组作为A**
引用,允许您在其中放置指向A
个对象的指针。对于B*
的数组,这是错误的,因此演员表是不安全的。
也许f
最好是模板功能:
template<typename T>
void f(T **array) {
...
}
答案 2 :(得分:1)
案件不正确。假设该函数是(完全合法的):
void f(A** foo)
{
foo[0] = new A();
}
现在如果你传递B** instead
,第一个指针(编译器肯定是B*
)突然变成A*
- 可怕的类型违规,硬崩溃可能很快。
A**
- 没有const
在眼前,请注意! - 表示指向 mutable 指针的 mutable 指针,这就是为什么将其中一个指针设置为A
的新指针是完全正常的原因。但是,如果你确实有一个B**
- 那些指针必须始终是B
(或子类),那么你不能这样做, 至A
,B
的超类。
是的,它的协方差和反方差一再重复 - 在可变性(看不到const
)的情况下,它真的是一个雷区。为什么不坚持你可能负担的所有const
?这也将表明哪些演员阵容在哪种情况下有意义!
答案 3 :(得分:0)
如果B
是A
的子类,那么你仍然可以对类型为B
的对象的指针列表进行排序,即使数组的类型是“指针数组{ {1}}”。
E.g。
A
但是,您想要的说是一种交换对象的通用算法,而不是基于指向对象值的指针。在这种情况下,您最好使用功能模板。
A** ptrToBs = new A*[10];
ptrToBs[0] = &b01; // ... or new B
ptrToBs[1] = &b02;
// ...
ptrToBs[9] = &b10;
f(ptrToBs);
通过这种方式,您可以对template< class T >
void f(T* t)
{
// ...
}
或A
数组进行排序,而无需使用指向正确类型的指针数组;您可以对B
或A
个对象或其他任何对象进行排序,前提是您排序的对象类型支持您在排序算法中使用的操作。
通常,您需要传递数组的大小或指向数组末尾的指针,以便算法不必假设数组有多大。
B
或
template< class T > void f(T* arr, std::size_t size);