在 C++ 中使用单例时解决循环依赖

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

所以我在使用单例 Game 类和 Story 类时遇到问题。

Game.hpp

#ifndef GAME_HPP
#define GAME_HPP

#include <memory>

class Phase; // Forward declaration

class Game
{
  private:
    static inline Game* instance_reference_{nullptr};
    std::unique_ptr<Phase> current_phase_;
    bool is_running_{true};

    explicit Game() {};
public:
    virtual ~Game();
    const static Game* getInstance();

当然,

getInstance()
方法是在.cpp文件中定义的。

Story.hpp

#ifndef PHASE_HPP
#define PHASE_HPP

class Game; // Forward declaration

class Phase
{
  protected:
    const Game* game_;
  public:
    explicit Phase() : game_{ Game::getInstance() } {};
    virtual ~Phase() = default;
    virtual void handlePhase() = 0;
};
#endif

还有一些其他类继承自Phase类。另外,目前没有

Phase.cpp
文件。

现在我无法编译,因为

Game::getInstance()
没有声明。 但是当我交换到
#include "Game.hpp"
而不是前向声明时,当我编译时,我收到此错误:

/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../include/c++/13.2.1/bits/unique_ptr.h:97:16: error: invalid application of 'sizeof' to an incomplete type 'Phase'
   97 |         static_assert(sizeof(_Tp)>0,
      |                       ^~~~~~~~~~~
/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../include/c++/13.2.1/bits/unique_ptr.h:404:4: note: in instantiation of member function 'std::default_delete<Phase>::operator()' requested here
  404 |           get_deleter()(std::move(__ptr));
      |           ^
./Game.hpp:36:14: note: in instantiation of member function 'std::unique_ptr<Phase>::~unique_ptr' requested here
   36 |     explicit Game() {};
      |              ^
./Game.hpp:13:7: note: forward declaration of 'Phase'
   13 | class Phase; // Forward declaration
      |       ^

总而言之,当我按照通常的方式实现它时,我在

Game::getInstance()
构造函数中调用
Phase
时遇到问题,但是当我尝试解决这个问题时,它仍然无法编译。

c++ singleton circular-dependency
1个回答
0
投票

首先,如果您使用 Meyer 的单例,您的问题会稍微简化:

static const Game& getInstance() {
    static Game instance;
    return instance;
}

其次,您应该在实际可以调用

Phase
的位置定义
getInstance()
的构造函数,例如在
.cpp
文件中:

#include "Game.hpp"

Phase::Phase() : game_{ &Game::getInstance() } {};

但是,当只有一场比赛时,存储

getInstance
的结果就没有什么意义了。 您始终可以通过
getInstance
访问游戏,那么
game_
有什么用呢?

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