如何使用has-a关系解析模板化循环依赖关系?

时间:2015-07-21 01:56:26

标签: c++

我有一个名为EntityManager的班级,Entity拥有vector。问题是,Entity在模板化函数中使用对EntityManager的引用。这是代码来证明我的意思:

//EntityManager.h
#include "Entity.h"
class EntityManager{
    std::vector<Entity> ents;
public:
    template<class T>
    void someFunc(const Entity & e){
        ...
    }
};

//Entity.h
#include "EntityManager.h"
class Entity{
    EntityManager * mgr;
public:
    template<class T>
    void someOtherFunc(){
        mgr->someFunc<T>(*this);
    }
}

注意,我试图将函数移出声明,如下所示:

//Entity.h
class EntityManager;

class Entity{
    EntityManager & mgr;
public:
    template<class T>
    void someOtherFunc();
}

#include "EntityManager.h"
template<class T>
void Entity::someOtherFunc(){
    mgr->someFunc<T>(*this);
}

如何解决此依赖关系?注意,我不能使用C ++ 11,以防隐藏解决方案。

1 个答案:

答案 0 :(得分:1)

看起来您的依赖关系如下:

  • EntityManager包含vectorEntity个。 EntityManager的类定义需要Entity的类定义才能明确定义。
  • Entity包含对EntityManager的引用。它的类定义需要EntityManager的类型声明 才能被明确定义。
  • EntityManager::someFunc<T>的实施需要EntityManagerEntity的类定义。
  • Entity::someOtherFunc<T>的实施还需要EntityManagerEntity的类定义。

所以,解决方案是:

  • Entity
  • 之前添加EntityManager的班级定义
  • EntityManager
  • 的类定义之前转发Entity
  • EntityManager的类定义之前包含Entity的类定义
  • 但要记住在实施EntityManager之前包含Entity::someOtherFunc<T>的类定义,以及在Entity
  • 实施之前包含EntityManager::someFunc<T>的类定义

这应该会打破这个循环。关键的见解是,尽管您通常可以内联编写成员函数模板,但在这种情况下,您必须将它们从类定义中分离出来。如果以声明方式表达依赖关系并使用适当的#include防护,则定义将自动包含在正确的顺序中。

例如,

<强> EntityManager.h

EntityManager的类定义需要Entity的类定义。标题需要包含EntityManager模板化成员函数的实现。

#ifndef ENTITYMANAGER_H
#define ENTITYMANAGER_H
#include "Entity.h"

class EntityManager {
  std::vector<Entity> ents;
public:
  template <typename T>
  inline void someFunc(const Entity &e);
};

#include "EntityManager.cpp.tmpl"

#endif

<强> EntityManager.cpp.tmpl

EntityManager的实施需要Entity的类定义。

#include "Entity.h"

template <typename T>
void EntityManager::someFunc(const Entity &e) {
  // do things with this, e, and T
}

<强> Entity.h

Entity的类定义只需要声明EntityManager类型。标题需要包含Entity模板化成员函数的实现。

#ifndef ENTITY_H
#define ENTITY_H
class EntityManager;

class Entity {
  EntityManager &mgr;
public:
  template <typename T>
  inline void someOtherFunc();
};

#include "Entity.cpp.tmpl"

#endif

<强> Entity.cpp.tmpl

Entity的实施需要EntityManager的类定义。

#include "EntityManager.h"

template <typename T>
void Entity::someOtherFunc() {
  mgr.someFunc<T>(*this);
}