我为每个循环迭代一个指针向量。指针是基类。在for each循环中,我使用派生类型作为迭代器的类型。渲染函数仅在某些派生类中定义,但代码编译并运行...如果向量包含指向不具有渲染函数的派生对象的指针(显然),它会崩溃。
for each (DerivedClass* body in myVector)
{
body->render();
}
我的代码中出现了这个错误,因为当我编写它时,向量只包含指向派生类的指针,但后来我决定重构代码并改变了。
有人能告诉我陷入此错误的正确方法吗?检查空指针似乎不起作用。
答案 0 :(得分:3)
真的,这里的问题是微软的foreach循环过于宽松。 Microsoft已弃用此扩展,转而使用标准的基于范围的for循环(自C ++ 11开始):
for (DerivedClass* body : myVector) {
body->render();
}
这里,循环的头部不会编译,因为它无法从DerivedClass*
初始化BaseClass*
。
关于实际编译,首先,请重新考虑您的设计。您应该编程接口,而不是实现。当某些物品不具有代码气味时,必须依赖这些物体进行渲染。也就是说,可以通过dynamic_cast
:
for (auto base : myVector) {
if (auto derived = dynamic_cast<DerivedClass*>(base)) {
derived->render();
}
}
没有C ++ 11(我只能假设缺少标准循环)?您仍然可以使用带索引或迭代器的传统for
循环。您还可以更明确地了解我的dynamic_cast
示例中的类型。
为了添加一点旋转,有时会出现这种类型的转换很常见的地方(例如,某些编译器实现)。如果确定这是一个很好的设计选择,您可以将此代码包装在算法中。例如,这是它在C#中的外观:
foreach (var body in myVector.OfType<DerivedClass>()) {
body.render();
}
答案 1 :(得分:1)
如果我理解正确,问题是只有向量中的某些指针指向实现render()
类型的对象。如果情况dynamic_cast
将执行检查正确类型的技巧。
for (DerivedClass *p : myVector) {
class_implementing_render *q = dynamic_cast<class_implementing_render>(p);
if (q) q->render();
}