假设我们有一个类 A 和类 B 和 C 继承自它。然后我们创建一个对 A 的引用数组,并用 B 和 C 填充它。现在我们决定要消除所有的 C。有没有一种方法可以检查数组的每个字段真正拥有的类型,而无需执行诸如 returnType() 函数之类的冗余操作?
编辑:将“A 的数组”固定为“A 的引用数组”。
假设我们有一个类 A 和类 B 和 C 继承自它。然后我们创建一个对 A 的引用数组,并用 B 和 C 填充它。现在我们决定要消除所有的 C。有没有一种方法可以检查数组的每个字段真正拥有的类型,而无需执行诸如 returnType() 函数之类的冗余操作?
编辑:将“A 的数组”固定为“A 的引用数组”。
您不能创建一个 As 数组并用 Bs 和 Cs 填充它 - 它们将被切成
As。您可以创建一个指向 A 的指针数组,您可以在其中填充指向 B 的指针和指向 C 的指针。
要在这种情况下检查某物的类型 - 使用动态转换:
// create B or C randomly
A * a = rand() % 2 ? new B : new C;
if ( dynamic_cast <B *> ( a ) ) {
// it's a B
}
else {
// it isn't (must be C in this case)
}
理想情况下,您想弄清楚是什么功能使您不希望 Cs 出现在其中。然后添加一个暴露该属性的虚函数。这样,当您添加也具有相同不需要的属性的 D 类时,事情将继续正常运行。
class A
{
public:
virtual bool IsFrobbable() { return true; }
};
class B : public A
{
};
class C : public A
{
public:
virtual bool IsFrobbable() { return false; }
};
int main()
{
vector<A *> vA;
vA.push_back(new A());
vA.push_back(new B());
vA.push_back(new C());
vA.erase(remove_if(vA.begin(), vA.end(), not1(mem_fun(&A::IsFrobbable))));
// Now go ahead and frob everything that's left
}
您将无法在其中存储 B。编译器会呻吟。
这仅在 A 的数组实际上是指向 A 的指针数组时才有效,否则您将遇到切片问题。
至于手头的问题,你最好给 A 一个虚函数 getClassName,并在子类中适当地覆盖它,然后使用结果来提供你想要的行为。
在 C++ 中创建引用数组是不可能的。
但是,可以创建指向 的指针数组A
。在这种情况下,如果A
声明了至少 1 个虚函数,您可以使用 C++ 的运行时类型推断 (RTTI) 机制来做您想做的事情:
A* arr[10];
fill_with_as_bs_and_cs(arr);
for (int i = 0; i < 10; ++i) {
if (dynamic_cast<C*>(arr[i])) {
arr[i] = 0; // You can't really "remove" things from an array...
}
}
然而,这不是最容易维护的方法——任何时候你需要区分 aC
和 anA
时,你都需要使用这个if
测试,如果你最终派生了更多的类A
并且你还需要区别对待它们,你将需要更新代码中执行此“类型测试”的每个位置。随着您的代码库变得越来越大,很快就会很容易错过一些地方。
通常,根据需要使用在每个类中重写的虚函数更易于维护。在这种特殊情况下,确定应该从数组中删除的所有派生类对象共享的一般标准A
是什么——假设一个对象如果是blargable则应该被删除——然后编写一个虚函数bool isBlargable()
,并测试相反。