(这个问题假设目标是全局+唯一对象。我想澄清一下,这并不意味着它在询问或提倡是否/为什么/何时使用/不使用单例或全局对象。)
我想知道我是否缺少关于 C++ 的技术细节,所以我的问题是:
C++ 中单例模式的命名空间实现是否有效?如果是这样,是否有理由不经常建议将其作为更好的方法?
从 Google 的风格指南中,我们看到命名空间非成员函数比静态成员函数更推荐,但仅在不共享静态数据时:
"Rather than creating classes only to group static member functions which do not share static data, use namespaces instead."
为什么要避免让非成员函数共享在未命名命名空间中声明的静态数据?这有什么不对的地方可以解释为什么通常不建议将 namespace 作为用 C++ 编写单例类的更好替代方法吗?
因为我找不到命名空间方法的建议,但是尽管 C++ 不强制使用类,但很容易找到类方法:
Can any one provide me a sample of Singleton in c++?
Singleton instance declared as static variable of GetInstance method
http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf
Singleton: How should it be used
在其源文件中使用命名空间和未命名空间:
- 您可以通过静态数据获得“状态”
- 将东西放在未命名的命名空间中可以获得额外的隐私
- 您仍然可以通过使用静态指针和从函数调用构造来控制其静态对象的构造顺序。
- 您不需要实现单例类
编辑 - 我正在考虑的 namespace 方法示例:
SingleThing.h:
namespace single_thing // The singleton (if this is actually valid)
{
void GrowSomeCats(int amount); // Typical setter
int GetNumCats(); // Typical getter
}
SingleThing.cpp:
#include "Balloon.h"
namespace // Acting like private members and functions
{
int numCats = 4; // POD
Balloon* wilson = NULL; // Not POD (and not a singleton)
// Contrived 'private' function
bool CanGrowCats()
{ return wilson && wilson->LikesCats(); }
// Contrived excuse to instantiate non-POD 'members'
void RandomlyCreateOtherObjects()
{
if (!wilson /* && someRandomiserImTooLazyToType()*/ )
wilson = new Balloon();
}
}
namespace single_thing // 'Public' functions
{
void GrowSomeCats(int amount)
{
RandomlyCreateOtherObjects();
if (CanGrowCats())
numCats += amount;
}
GetNumCats()
{ return numCats; }
}
最佳答案
(我假设我们都同意全局状态是一种危险的东西,必须特别小心使用。)
从技术上讲,您的单例命名空间等同于单例类。然而,它有一个主要缺点,这在我看来是不可取的:它隐藏了它是有状态的这一事实。曾经使用过std::strtok( )
?还记得那是多么可怕的一团糟吗?那是因为它也隐藏了它的状态。
因为全局状态本质上是危险的,所以使用它的任何功能都应该在调用站点充分清楚地说明这一事实,最好是使用语言结构——因为没有人会阅读评论或文档。 Foo::instance()->do_work();
是一种已知的模式,可以清楚地表明正在发生一些特殊的事情; foo::do_work();
没有。
关于c++ - 单例实现 : Is a namespace approach often preferable over a singleton class?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46860068/