如何在C ++中以正确的方式使用类的向量处理多态?

时间:2019-04-27 21:09:22

标签: c++ pointers templates vector polymorphism

我当前正在实现一个实体组件系统,并正在研究一种存储组件向量的方法,一个组件类型的每个向量都应该是连续的,这就是为什么我使用vector<Component>*而不是{{1 }}。我是C ++的新手,来自Java,所以我仍在与有关内存布局和多态性的一些概念作斗争。

我已经完全实现了(看似)这个版本。我对每种类型的组件都有一个向量(例如PositionComponent,GravityComponent等),因为组件的大小不同。但是因为类型的数量在编译时未知,所以我需要一个指针向量来指向这些不同类型的ComponentList。我正在将reinterpret_casts与一个映射一起使用,该映射跟踪组件类型来完成此操作,但是必须有一种不太明确的方式来执行此操作。 (希望如此!)

这是我要实现的目标的图片: Component List Layout

编辑:我只是注意到我的程序在主功能中的vector<Component*>之后由于段错误而崩溃。调用栈似乎已损坏,因为它跳转到某个随机地址而不是实际返回。所以我的系统肯定有缺陷。

主要功能:

return 0

EntityComponentSystem类:

int main(int argc, char** argv)
{
    EntityComponentSystem ecs;

    // Fill with some components
    for(int i = 0; i < 5; ++i)
    {
        ecs.addComponent(AComponent());
        ecs.addComponent(BComponent());
        ecs.addComponent(CComponent());
    }

    // Print all components
    std::cout << "Components: " << std::endl;

    // Print AComponents
    std::cout << "A Components: " << std::endl;
    ComponentList<AComponent>* aComps = ecs.getComponentList<AComponent>();
    aComps->print();

    // Print BComponents
    std::cout << std::endl << "B Components: " << std::endl;
    ComponentList<BComponent>* bComps = ecs.getComponentList<BComponent>();
    bComps->print();

    // Print CComponents
    std::cout << std::endl << "C Components: " << std::endl;
    ComponentList<CComponent>* cComps = ecs.getComponentList<CComponent>();
    cComps->print();

    return 0;
}

ComponentList类:

class EntityComponentSystem
{
    private:
        // To shorten some things up
        typedef std::vector<ComponentList<Component>*>::iterator                    ComponentListIterator;
        typedef std::unordered_map<std::type_index, Component::TypeID>::iterator    MapIterator;

        std::vector<ComponentList<Component>*>                  comps;          // Indexed by TypeID
        std::unordered_map<std::type_index, Component::TypeID>  componentMap;   // Maps typeid(Component) to TypeID

    public:
        EntityComponentSystem() : comps(), componentMap() {}
        ~EntityComponentSystem()
        {
            for(ComponentListIterator it = comps.begin(); it < comps.end(); ++it)
            {
                delete (*it);
            }
        }

        template<typename T>
        void addComponent(const T& component)
        {
            static_assert(std::is_base_of<Component, T>::value, "T must be of type Component!");

            MapIterator found = componentMap.find(typeid(T));
            ComponentList<T>* componentList = nullptr;

            if(found == componentMap.end()) // This component derivative hasn't been added yet, so add it
            {
                componentList = new ComponentList<T>();
                int componentId = comps.size();
                this->comps.push_back(reinterpret_cast<ComponentList<Component>*>(componentList));
                this->componentMap[typeid(T)] = componentId;
            }
            else
            {
                componentList = reinterpret_cast<ComponentList<T>*>(comps[found->second]);
            }

            componentList->push(component);
        }

        template<typename T>
        ComponentList<T>* getComponentList()
        {
            Component::TypeID id = getComponentTypeId<T>();
            if(id == Component::TYPE_ID_UNKNOWN) return nullptr;
            return reinterpret_cast<ComponentList<T>*>(comps[id]);
        }

        template<typename T>
        Component::TypeID getComponentTypeId()
        {
            static_assert(std::is_base_of<Component, T>::value, "T must be of type Component!");

            MapIterator found = componentMap.find(typeid(T));

            if(found == componentMap.end())
            {
                return Component::TYPE_ID_UNKNOWN;
            }

            return found->second;
        }
};

基本组件类及其派生类:

template<typename T>
class ComponentList
{
    private:
        std::vector<T>      components;

    public:
        void push(const T& t)
        {
            this->components.push_back(t);
        }

        void print()
        {
            for(typename std::vector<T>::iterator it = components.begin(); it != components.end(); ++it)
            {
                it->test();
            }
        }
};

0 个答案:

没有答案