C++ 使用单例和子类的循环包含

C++ 使用单例和子类的循环包含,c++,inheritance,singleton,circular-dependency,C++,Inheritance,Singleton,Circular Dependency,在做我的一个小游戏时,我遇到了一个循环依赖相关的问题 假设我使用2个类和一个助手名称空间(都包括guarded),其中Base是主游戏类,Player是Player对象和Entity的子对象,helper是负责处理平铺冲突的函数名称空间: 当我试图编译代码时,Player在base.h中没有被识别为类型说明符,我还得到了一个未知的覆盖说明符。当我向前宣布球员时,它是未定义的,尽管我包括球员.h。 我一直在互联网上寻找解决方案,但没有一个典型的循环包含解决方案是适用的。如上所述,我尝试了各种前向声

在做我的一个小游戏时,我遇到了一个循环依赖相关的问题

假设我使用2个类和一个助手名称空间(都包括guarded),其中Base是主游戏类,Player是Player对象和Entity的子对象,helper是负责处理平铺冲突的函数名称空间:

当我试图编译代码时,Player在base.h中没有被识别为类型说明符,我还得到了一个未知的覆盖说明符。当我向前宣布球员时,它是未定义的,尽管我包括球员.h。 我一直在互联网上寻找解决方案,但没有一个典型的循环包含解决方案是适用的。如上所述,我尝试了各种前向声明的组合,但它只改变了错误的类型

我想知道是否有人能注意到下面代码中的任何缺陷

(请注意,我将所有函数实现放在标题中只是为了演示,它们有自己的小cpp文件)

base.h

#include "player.h"
#include "level.h"
class Base{
   static Base& instance() 
   {
        static Base base;
        return base;
   }
   Player player;
   Level level;
}
实体.h

class Entity{
    vec2 velocity; //Assume we are using the glm library
    vec2 position;
    virtual void update()
    {
    }
}
player.h

#include "helper.h"
#include "entity.h"
class Player:public Entity{
    void update()
    {
        velocity=helper::tileCollision(velocity);
        //Update position and stuff
    }
}
助手

#include "level.h"
#include "base.h"
namespace helper{
    vec2 tileCollision(vec2 velocity)
    {   
         Level& level = Game::instance().level;
         //Pop some fancy tile collision math in here
         return vec2(0);
    }
}

首先,请不要在头中编写函数的实现,除非它不是内联的或模板的

请尝试以下操作:

base.h

#include <memory>

class Player;
class Level;

class Base {
   public:
        static Base& instance();

   private:
       Base();
       unique_ptr<Player> player;
       unique_ptr<Level> level;
}
#包括
班级运动员;
班级层面;
阶级基础{
公众:
静态基&实例();
私人:
Base();
独特的ptr播放器;
独特的ptr水平;
}
base.cpp

#include "base.h"
#include "player.h"
#include "level.h"


Base::Base() : Player(make_unique<Player>()), Level(make_unique<Level>())
{
}


static Base& Base::instance() 
{
    static Base base;
    return base;
}
#包括“base.h”
#包括“player.h”
#包括“h级”
Base::Base():播放器(使_唯一()),级别(使_唯一())
{
}
静态基&Base::instance()
{
静基座;
返回基地;
}
你应该注意以下几点:

您只显示了代码的一些片段,并附带了不合适的描述(转发声明在哪里?)并且留给我们太多的幻想。改为创建一个MCVE。“不要在头中编写代码”-也许更好的表达方式是“不要在头中编写函数的实现”:@Alex我觉得在这个示例中添加cpp文件是不必要的,这是完全独立的。但是,尽管这是一个有效的解决方案,但我不理解为什么没有合适的方法让一个单例的常规值成员(Base::instance().player类型)使用一个助手名称空间(helper),使用同一单例的另一个成员(Base::instance().level)。你愿意解释一下吗?