我正在尝试逐个处理类实例。 我有一个抽象基类(这里是IBase),它包含一个doStuff方法。 此方法将在扩展类中重写,以便处理所有其他已定义的类。
这是我正在建造的图书馆的一部分。我希望库用户可以编写Base对象。每个Base类都需要通过doStuff方法与另一个Base对象进行交互。需要容器来处理多个Base对象。
这不是我第一次遇到这个问题,但我不记得我最后一次怎么做了。这种类可以用于很多事情。这是一个碰撞检测系统。 IBase代表一个抽象的HitBox,Container代表碰撞发生的场景。在这种情况下,Container :: process检查命中框之间的转换,而Container :: process用于实现优化算法(quadtree,...)。
我用这种方式构建了这些类:
class IBase {
public:
virtual void doStuff(IBase* base) = 0;
}
class Base {
public:
virtual void doStuff(Base* base) {
foobar();
}
virtual void doStuff(IBase* base) {
// irrelevant
}
}
class Container {
public:
void process() {
for (std::list<IBase*>::iterator it=base_list.begin() ; it!=base_list.end() ; it++) {
for (std::list<IBase*>::itarator jt=std::next(it) ; jt!=base_list.end() ; jt++) {
(*it)->doStuff(*jt);
}
}
}
private:
std::list<Ibase*> base_list;
}
但是在循环中,当使用两个Base对象时,我无法达到void Base :: doStuff(Base *)。 我只能调用Base :: doStuff(IBase *),这不是我想要的。
对此有任何帮助吗?我理解这个问题,但我看不到它的解决方案。这是处理它的好方法还是我需要再次思考我的架构?你会怎么做?我认为这样的问题必须存在设计模式,但我没有发现任何适合的设计模式。
由于
答案 0 :(得分:2)
C ++不支持参数的逆变。另请参阅Why is there no parameter contra-variance for overriding?。
您可能最好从doStuff(Base* base)
正文中明确调用doStuff(IBase* base)
。
答案 1 :(得分:1)
当您从*it
和*jt
取消引用时,您的对象被引用为IBase
个对象,而不是Base对象。这意味着只能调用IBase
中的方法。
您的虚拟方法:
virtual void doStuff(Base* base) { ... }
并未覆盖任何内容。它正在创建一个 new 虚拟方法,只能从Base向下访问。当您从doStuff
指针拨打IBase
时,它会致电:
virtual void doStuff(IBase* base) { ... }
与IBase
中定义的签名相匹配。
如果您要执行foobar
功能,当base
基于覆盖doStuff
时,应对其进行某种检查,并将其投放到{{} 1}}一旦你确定它是安全的,那么根据需要使用它。
Base*
最后,如前所述,将virtual void doStuff(IBase* base) {
// not irrelevant
if (base->isBase())
{
foobar();
}
}
公开。