我目前有以下结构
class A
class B : public A
class C : public A
我在A中定义了虚拟方法,B和C正在重写它们。这些方法是排序的。
bool C::CheckCollision(shared_ptr<B> box);
bool B::CheckCollision(shared_ptr<C> triangle);
我也有一个向量的shared_ptr<A>,我存储所有的游戏对象。问题是我不能做以下事情
for (int i = 0; i < objects.size(); i++)
{
for (int j=i; j < objects.size(); j++
{
objects[i]->CheckCollision(objects[j]);
}
}我收到一个错误,说明参数列表与重载函数不匹配。当我试图通过shared_ptr<A> (我期望shared_ptr<B>或shared_ptr<C> )的地方时,这是有意义的,但是我如何绕过这个问题呢?还有别的办法吗?
发布于 2019-03-03 12:59:50
让我们让它使用虚拟函数和指向基类的共享指针
首先,您可以使用指向基的共享指针完美地使多态性工作。这里有一个小片段,向您展示如何做到这一点:
class A {
public:
virtual void show() { cout<<"A"<<endl; }
virtual void collide(shared_ptr<A> a) { cout<<"collide A with "; a->show(); }
virtual ~A() {}
};
class B : public A {
public:
void show() override { cout<<"B"<<endl; }
void collide(shared_ptr<A> a) override { cout<<"collide B with "; a->show(); }
};
class C : public A {
public:
void show() override { cout<<"C"<<endl; }
void collide(shared_ptr<A> a) override { cout<<"collide C with "; a->show(); }
};然后,您的双循环将看起来如下:
vector<shared_ptr<A>> objects;
objects.push_back (make_shared<A>()); // populate for the sake of demo
objects.push_back (make_shared<B>());
objects.push_back (make_shared<C>());
for (int i = 0; i < objects.size(); i++)
{
objects[i]->show();
for (int j=i; j < objects.size(); j++)
{
objects[i]->collide(objects[j]); // note that you have to use -> not .
}
}现在,为了掌握这些组合,我使用了一个覆盖,它知道它自己的对象的真实类型,但不知道合作伙伴对象的真实类型。因此,为了确定它是哪种配对,我需要调用合作伙伴对象的多态函数。
解决您的问题的更普遍的方法是双重分派。
这个概念的小证明是为了给出一个简单的例子。当问题可以在每个执行问题一部分的合作伙伴对象中被分解时,这是非常理想的。但是事情并不总是那么简单,所以你可以通过谷歌搜索双重调度找到更复杂的技术。幸运的是,这种碰撞的例子相当常见。
这里,另一个演示使用重写和重载的组合。我认为这是你试图实现的事情,但通过一个层次的间接解决它更多。它是受游客模式的启发:使用指向合作伙伴对象基类的共享指针调用对象的多态冲突函数。但是,该函数的实现立即调用合作伙伴对象的多态函数,并将其作为参数引用自身(即对参数的真实类型的了解,允许编译器选择正确的重载)。这种“反弹”方法(顺便说一句,它是一种反向访问者)不幸地要求基类了解其所有潜在的派生类,这是非常不理想的。但它允许为每一个可能的组合提供不同的行为。
另一种双重分派方法是使用调度表。THis的工作方式是管理一种虚拟表,但使用两种类型,并对调用正确组合的正确函数进行一些查找。
https://stackoverflow.com/questions/54968690
复制相似问题