在大型框架中定义和访问对象

时间:2014-12-08 05:22:25

标签: c++ oop design-patterns singleton

在一个需要实现的大型框架中定义包装类对象(在main之外)的好方法是什么,可以从任何地方访问它们。

(例如在Player.cpp等游戏对象中使用Clock.Get_Deltatime()并在main.cpp中运行Clock.Update())

我可以这样做吗?

#ifndef PLUGIN_H
#define PLUGIN_H

#include "DisplayManager.h"
#include "EventHandler.h"
#include "Time.h"

DisplayManager Display;
EventHandler Input;
Time Clock;

#endif PLUGIN_H

除了我需要访问显示,时钟和输入之外,还包括Plugin.h?考虑到这一点,单身人士和静态变量现在,但我正在寻找建议,并想知道什么将最适合这种情况(我是相对较新的C ++,没有足够的OOP经验,知道什么是最好的工具,为作业)。

2 个答案:

答案 0 :(得分:1)

上面的代码可以使用,但您需要使用extern关键字声明变量,以便每次包含标头时编译器都不会生成新的全局变量。在应用程序的一个位置声明没有extern关键字的全局变量,这将是变量实际初始化的位置。

而不是上述我建议采用以下模式。我将使用DisplayManager作为示例:

DisplayManager.h:

#ifndef DISPLAY_MANAGER_H_
#define DISPLAY_MANAGER_H_

class DisplayManager {
 public:
  static DisplayManager* Get();

  // Any other public interfaces.

 private:
  // Declare the constructor private or protected to prevent instances other
  // than the singleton.
  DisplayManager();
  ~DisplayManager();

  // Any other private functions or members.
};

DisplayManager.cpp:

#include "DisplayManager.h"

static DisplayManager* g_display_manager;

DisplayManager* DisplayManager::Get() {
  if (!g_display_manager) {
     g_display_manager = new DisplayManager();
  }
  return g_display_manager;
}

...

这种方法将单例行为封装在类本身中。

答案 1 :(得分:1)

这个答案使用C ++ 11

在单线程环境中,单例的跟随模式运行良好:

#include <memory>

class DisplayManager
{
public:
  static DisplayManager* instance()
  {
    static std::unique_ptr<DisplayManager> ptr(new DisplayManager);
    return ptr.get();
  }
private:
  friend struct std::default_delete<DisplayManager>;
  DisplayManager() {}
  ~DisplayManager() {}
  DisplayManager(const DisplayManager& rhs) {}
  DisplayManager& operator= (const DisplayManager& rhs) { return *this; }
};

如果您需要确保从多个线程正确访问,请将其更改为:

#include <memory>
#include <mutex>

class DisplayManager
{
public:
  static DisplayManager* instance()
  {
    static std::unique_ptr<DisplayManager> ptr;
    static std::mutex m;
    if (!ptr)
    {
      m.lock();
      if (!ptr) ptr.reset(new DisplayManager);
      m.unlock();
    }
    return ptr.get();
  }
private:
  friend struct std::default_delete<DisplayManager>;
  DisplayManager() {}
  ~DisplayManager() {}
  DisplayManager(const DisplayManager& rhs) {}
  DisplayManager& operator= (const DisplayManager& rhs) { return *this; }
};