我对使用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
而不“破坏”我的命名空间。某种“命名空间 - 本地”定义?
答案 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
。关于最后一点的说明:如果您担心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