下面是一些说明问题的代码:
#include <iostream>
class Base {
};
class Derived : public Base {
};
void doThings(Base* bases[], int length)
{
for (int i = 0; i < length; ++i)
std::cout << "Do ALL the things\n";
}
int main(int argc, const char * argv[])
{
Derived* arrayOfDerived[2] = { new Derived(), new Derived() };
doThings(arrayOfDerived, 2); // Candidate function not viable: no known conversion from 'Derived *[2]' to 'Base **' for 1st argument
// Attempts to work out the correct cast
Derived** deriveds = &arrayOfDerived[0];
Base** bases = dynamic_cast<Base**>(deriveds); // 'Base *' is not a class
Base** bases = dynamic_cast<Base**>(arrayOfDerived); // 'Base *' is not a class
// Just pretend that it should work
doThings(reinterpret_cast<Base**>(arrayOfDerived), 2);
return 0;
}
Clang 会产生注释中给出的错误。问题是:“是否有正确的方法将 arrayOfDerived
转换为 doThings
可以接受的东西?
加分:
- 为什么 clang 在给定行上产生错误“
'Base *' is not a class
”?我知道Base*
不是一个类,它是一个指针。试图告诉我的错误是什么?为什么有dynamic_cast
被设计成在dynamic_cast<T*>
东西T
必须是一个类(class)吗? - 使用
reinterpret_cast
有什么危险?强制一切正常工作?
一如既往的感谢:)
最佳答案
没有。您在这里要求的是协变数组类型,这不是 C++ 的特性。
reinterpret_cast
或 C 风格转换的风险在于,虽然这适用于简单类型,但如果您使用多重继承或虚拟继承,它会失败得很惨,并且还可能破坏虚函数的存在(取决于实现)。为什么?因为在那些情况下,static_cast
或 dynamic_cast
实际上可能会更改指针值。即给定
class A {
int a;
};
class B {
string s;
};
class C : public A, B {
double f[4];
};
C *ptr = new C();
除非类为空,ptr == (A *)ptr
和/或 ptr == (B *)ptr
将为 false
。只需要一点时间就可以弄清楚为什么一定是这样。如果你使用单继承并且没有虚表,那么可以保证子类的布局与父类(super class)的布局相同,后面是子类中定义的成员变量。但是,如果您有多重继承,则编译器必须选择以某种顺序或其他方式对类进行布局;我不确定 C++ 标准对此有何规定(您可以检查 - 它可能以某种方式定义或限制布局顺序),但无论它选择什么顺序,很明显其中之一强制转换必须导致指针值发生变化。
关于c++ - 将指向派生类的指针数组转换为指向基类的指针数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24785760/