通过父类访问子类变量

问题描述 投票:0回答:1

我正在为圆形和正方形制作一个简单的 2D 物理引擎。我有一个主体类,我希望在创建时为其提供一个形状的 unique_ptr 实例。形状可以是圆形或盒子。身体是我想放入游戏循环以检查碰撞的对象。在检查碰撞时,我对与形状相关的数据感兴趣。一个非常原始的例子如下所示:

#include <iostream>
#include <memory>

struct Shape
{
    virtual float calculateArea() const = 0;
};

struct Circle: public Shape
{
    const float m_radius;
    Circle(float radius) : m_radius(radius) {} 
    float calculateArea() const {return m_radius*m_radius*3.14;}
};

struct Square: public Shape
{
    const float m_side_length;
    Square(float side_length) : m_side_length(side_length) {}
    float calculateArea() const {return m_side_length*m_side_length;}
};

struct Body
{
    Body(std::unique_ptr<Shape>& shape): m_shape(std::move(shape)) {}
    std::unique_ptr<Shape> m_shape;
};



int main() 
{
    std::unique_ptr<Shape> circ = std::make_unique<Circle>(5.0);
    std::unique_ptr<Shape> square = std::make_unique<Square>(10.0);
    std::shared_ptr<Body> body1 = std::make_shared<Body>(circ);
    std::shared_ptr<Body> body2 = std::make_shared<Body>(square);
}

本质上,我想知道是否有办法访问形状的半径或形状的边长。我可以看到类似的东西

body1->shape->m_radius
body2->shape->m_side_length
不起作用,但我真的想找到一个解决方案,可以将我的形状分组为通用形状类,并且我仍然能够通过 body 类访问它们的独特功能。顺便说一句,这是为了碰撞检测。

我看到了一些相关的帖子,例如这里:通过基类指针C++访问派生类的成员,但总体问题与我的略有不同,而且问题相当老了。

感谢您的帮助 - 希望它有意义!

c++ class inheritance smart-pointers
1个回答
0
投票

你说

我想知道是否有办法访问形状的半径或形状的边长。

是的,有多种方法可以获取派生类成员,但我不建议采用这种方法来解决您的编程问题。它很快就会长毛。

假设

shape
有 N 个子类。给定两个
shape
对象,如果碰撞检测逻辑取决于对象类型,则您将需要 NC2 函数来覆盖功能。

实现此目的的一种方法是拥有检测逻辑类/函数的注册表。您可以在程序启动时向注册表添加条目。您将需要添加代码来查找两个对象类型的类/函数的注册表,然后调用这些函数。在实现检测逻辑的类/函数中,使用

dynamic_cast
来获取特定对象类型并从特定对象类型中获取必要的数据是公平的。

这是其中的概述。

class CollisionDetector
{
    virtual bool detectCollision(
        shape const& shape1,
        shape const& shape2) const;
};

class CollisionDetectorRegistry
{
    using CollisionDectorBuilder = CollisionDetector*(void);

    static void registerCollisionDetector(
        std::string const& shapeType1,
        std::string const& shapeType2,
        CollisionDectorBuilder builder);

    static CollisionDetector* getCollisionDetector(
        shape const& shape1,
        shape const& shape2);
};

class CircleCircleCollisionDetector : public CollisionDetector
{
    virtual bool detectCollision(
        shape const& shape1,
        shape const& shape2) const;

    static CollisionDetector* build();
}

class CircleSquareCollisionDetector : public CollisionDetector
{
    virtual bool detectCollision(
        shape const& shape1,
        shape const& shape2) const;

    static CollisionDetector* build();
}

// Add the following in some place that is executed at start up time.

CollisionDetectorRegistry::registerCollisionDetector(
   "circle", "circle", CircleCircleCollisionDetector::build);

CollisionDetectorRegistry::registerCollisionDetector(
   "circle", "square", CircleSquareCollisionDetector::build);

// Shape-independent function for detecting collision
bool detectCollision(
    shape const& shape1,
    shape const& shape2)
{
    CollisionDetector* detector = 
        CollisionDetectorRegistry::getCollisionDetector(shape1, shape2);
    if ( detector == nullptr )
    {
       // Throw an execption.
    }
    else
    {
        return detector->detectCollision(shape1, shape2);
    }
}

我意识到你需要填补一些空白,但我假设你可以做到。

© www.soinside.com 2019 - 2024. All rights reserved.