传递shared_ptr作为<Base>shared_ptr<Derived>

Passing shared_ptr<Base> as shared_ptr<Derived>

本文关键字:shared gt lt ptr Derived Base 作为 传递      更新时间:2023-10-16

i当前有以下结构

class A

class B : public A

class C : public A

我在A中定义了虚拟方法,BC正在覆盖它们。这些方法是

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>的地方很有意义,但是我该如何解决这个问题?还有另一种方法吗?

让我们与虚拟函数一起使用,并共享指针

首先,您可以使用共享的指针完美地使多态性起作用。这里是一个小片段,向您展示如何做到这一点:

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 .
    }
}

现在,您会看到,为了掌握组合,我使用了一个了解其对象的真实类型但对合作伙伴对象的实际类型不了解的替代。因此,要确定它是哪种配对,我需要调用合作伙伴对象的多态性功能。

在线演示

您问题的更通用的方法是double dispatch

这个小的概念证明是显示一个简单的例子。当问题可以分解为问题的每个伙伴对象中,这是理想的选择。但是事情并不总是那么简单,因此您可以通过搜索 double Dispatch 来找到更多精心设计的技术。幸运的是,碰撞的例子很普遍。

在这里,另一个结合了覆盖和超载的演示。我认为这是您尝试实现的目标,但可以通过一个间接级别来解决它。它的灵感来自访问者模式:对象的多态性碰撞函数由共享指针指向合作伙伴对象的基类。但是,此函数的实现立即将合作伙伴对象的多态函数称为"参数"作为对本身的引用(即对参数的真实类型的了解,允许编译器选择正确的过载)。不幸的是,这种"反弹"方法(顺便说一句,这是一种倒置的访客)要求基础类别阶层知道其所有潜在派生类,这远非理想。但是它允许为每种可能的组合提供不同的行为。

双重调度的另一种方法是使用调度表。这是通过管理一种虚拟表但具有两种类型的方法来工作的,并且有一些查找以调用正确组合的正确功能。