C ++ Singleton #define

时间:2016-02-13 10:45:51

标签: c++ singleton

我对使用C ++的单例模式提出了一个小问题。 假设我有以下课程:

namespace MyNameSpace 
{
   class Window_Singleton 
   {
   private:
      static Window_Singleton instance;
      Window_Singleton();
      /* Some more private stuff here */

   public:
      static Window_Singleton *GetInstance();
      ~Window_Singleton();
      /* Some more public stuff here */

   }
}

#define Window Window_Singleton.GetInstance()

我有#define这样我就不必总是写MyNameSpace::Window_Singleton.GetInstance().SomeMethod(),我现在可以使用较短的MyNameSpace::Window.SomeMethod()

但问题是:现在我不能在另一个名称空间中创建一个Window类,因为我会遇到定义问题。

有没有办法提供#define而不“破坏”我的命名空间。某种“命名空间 - 本地”定义?

4 个答案:

答案 0 :(得分:2)

由于宏在编译之前是扩展的,因此预编译器不会知道诸如类,命名空间等内容。所以不,如果您定义宏Window,它将在任何地方使用。

你可以做的是定义一个函数:

inline Window_Singleton& Window(){
  return Window_Singleton.GetInstance();
}

然后写

Window().SomeMethod();

它基本上是另外一对括号,但它会让你的代码更清晰。

答案 1 :(得分:1)

我强烈建议你不要在这里使用game.batch.setProjectionMatrix(gameCam.combined); game.batch.begin(); game.batch.draw(ball, player.b2Body.getPosition().x - MarioBros.RADIUS_CHARACTER / MarioBros.PPM, player.b2Body.getPosition().y - MarioBros.RADIUS_CHARACTER / MarioBros.PPM, 70 / MarioBros.PPM, 70 / MarioBros.PPM); colture.setColor(256, 256, 256, 1); colture.draw(game.batch,"Hello m8", 10 / MarioBros.PPM,10 / MarioBros.PPM); endOfGame(); game.batch.end(); 。它实际上并没有垃圾邮件命名空间,但它可以完成任何包含此定义的代码,并且很难找到错误。例如,一旦定义了符号#define,就会出现一个函数

Window

已损坏,在某些情况下,您将很难发现此类错误。此外,它使您的代码更难阅读。如果我想调用静态函数来获取实例并调用方法,我希望代码看起来像这样:

Foo(Bar* Window){ /*...*/}

,而

Window_Singleton::GetInstance().SomeMethod();

看起来更像是调用某个全局实例的方法。我的意思是你可以使用全局

Window.SomeMethod();

但据我所知,你不想使用全局的单身人士。总结:如果代码反映了您真正想要做的事情,那么您的代码很容易阅读。当看起来像调用静态方法时,调用静态方法最不模糊。如果你懒得键入,请使用一些代码完整的编辑器,但不要使用有潜在危险的定义使代码更难阅读。

PS:我必须提到,在我的评论中,我有点困惑。 Window_Singleton Window; 完全不知道名称空间。在编译器开始实际工作之前,它们在代码中被替换。这就是为什么将#defines引起的编译器错误与定义符号的地方联系起来很困难(如果不是不可能)。

答案 2 :(得分:1)

  

有没有办法提供#define而没有"打破"我的命名空间   某种"命名空间 - 本地"定义

简短回答:不。

更长的答案:宏没有范围。无论好坏,这就是它们与其他C ++功能的区别所在。

完整答案:

  • 如果可以避免使用宏,请不要使用宏。
  • 如果您使用任何宏,请使用ALL_CAPS
  • 根本不要使用Singleton模式。
  • 轻松写作不是代码质量的相关因素。

关于最后一点的说明:如果您担心MyNameSpace::Window_Singleton.GetInstance().SomeMethod()太长而无法阅读,那么我当然可以同情这一点。但这仍然不是用宏来感染你的代码的理由。您应该在本地范围使用using,引用可能auto以提高可读性。例如:

void f()
{
    using MyNameSpace::Window_Singleton;
    auto& window = Window_Singleton.GetInstance();

    window.SomeMethod();
}

答案 3 :(得分:0)

我认为没有办法使用宏,忽略范围规则。

您可以考虑使用typedef:

namespace MyNameSpace 
{
   class Window_Singleton 
   {
   // ...
   };

   typedef Window_Singleton  WS;

// ...
}

您的代码现在可以使用typedef'd同义词/别名...

// WS is alias/synonym for Window_Singleton
MyNameSpace::WS::SomeMethod();   // access to static method

MyNameSpace::WS  ws;   // declare instance
ws.SomeMethod2();       // access instance

提示 - 我尝试将命名空间名称限制为3个字母。考虑

namespace ETB;  // for Exhauzt Tool Box

namespace EWS;  // for Exhauzt Window Singleton