2016-02-13 65 views
0

我对使用C++的单例模式有个小问题。 比方说,我有下面的类:C++单例#define

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没有“打破”我的名字空间。某种“名称空间本地”定义?

+1

的方式不使'#define' “破发” 的命名空间是不是在这里使用一个'#define'。你主要用它混淆你的代码,只是不这样做,你不会有问题 – user463035818

+0

但是,我没有更短的方式来访问我的单身人士 – danielspaniol

+0

如果你懒得打字你应该使用IDE而不是让你的代码难以读取和发送命名空间 – user463035818

回答

2

由于宏是在编译之前扩展的方式,预编译器并不知道类,名称空间等等。所以不行,如果你定义了一个宏Window它将在任何地方使用。

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

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

,然后写

Window().SomeMethod(); 

这基本上是一个额外的一对大括号,但它会保持你的代码更清晰了很多。

1

我强烈建议您不要在这里使用#define。它实际上不会垃圾邮件名称空间,但它可以完成任何代码,包括这个定义很难找到错误。例如,一旦符号Window定义,函数

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

被打破,在某些情况下,你将有一个艰难的时间来发现这样的错误。此外,它使你的代码更难阅读。如果我要调用静态函数来获取一个实例,并调用一个方法,我希望的代码看起来像这样:

Window_Singleton::GetInstance().SomeMethod(); 

Window.SomeMethod(); 

看起来更像是调用一些全球性的方法实例。我的意思是你可以使用全球

Window_Singleton Window; 

但据我所知,你不想使用一个全局的单身人士。总之:如果它反映了你真正想要做的事情,你的代码很容易阅读。调用静态方法在调用静态方法时最不容易混淆。如果您懒得输入,请使用一些带有代码补全的编辑器,但是请勿使用潜在危险的定义使您的代码难以阅读。 PS:我不得不提到,在我的评论中,我有点困惑。 #defines完全不知道名称空间。在编译器开始实际工作之前,将它们替换为代码。这就是为什么将#defines引起的编译器错误与符号定义的地方联系起来可能很困难(如果不是不可能的话)。

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(); 
} 
0

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

你可能会考虑一个typedef:

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

    typedef Window_Singleton WS; 

// ... 
} 

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

// 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