首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将shared_ptr<Base>传递为shared_ptr<Derived>

将shared_ptr<Base>传递为shared_ptr<Derived>
EN

Stack Overflow用户
提问于 2019-03-03 12:16:17
回答 1查看 87关注 0票数 0

我目前有以下结构

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>,我存储所有的游戏对象。问题是我不能做以下事情

代码语言:javascript
复制
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> )的地方时,这是有意义的,但是我如何绕过这个问题呢?还有别的办法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-03 12:59:50

让我们让它使用虚拟函数和指向基类的共享指针

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

代码语言:javascript
复制
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();  } 
};

然后,您的双循环将看起来如下:

代码语言:javascript
复制
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的工作方式是管理一种虚拟表,但使用两种类型,并对调用正确组合的正确函数进行一些查找。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54968690

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档