【发布时间】:2011-12-09 18:35:20
【问题描述】:
对于我正在进行的一个项目,我有一堆“库类”。这些本质上是价值相关功能的集合。其中一些库需要在运行时“初始化”。到目前为止,我一直在使用以下设计作为解决方案:
// Filename: Foo.h
namespace my_project
{
namespace library
{
class Foo
{
public:
static int some_value; // members used externally and internally
Foo()
{
// Lots of stuff goes on in here
// Therefore it's not a simply member initialization
// But for this example, this should suffice
some_value = 10;
Foo::bar();
}
static void bar() { ++some_value; } // some library function
// no destructor needed because we didn't allocate anything
private:
// restrict copy/assignment
Foo(const Foo&);
void operator=(const Foo&);
};
int Foo::some_value = 0; // since some_value is static, we need this
} // library namespace
static library::Foo Foo;
} // my_project namespace
使用Foo 与此类似,例如:
#include "Foo.h"
using namespace my_project;
int main()
{
int i = Foo.some_value;
Foo.bar();
int j = Foo.some_value;
return 0;
}
当然,这个例子非常简单,但它抓住了重点。这种方法对我来说有四个好处:
库的用户无需担心初始化。他们不需要在
main()中调用类似Foo::init();的东西,因为library::Foo是在构造my_project::Foo时初始化的。这是这里的主要设计约束。 用户应该不负责初始化库。我可以在库中创建各种私有函数来控制它的使用。
用户可以出于任何原因选择创建此库的其他实例。但不允许复制。默认情况下会为他们提供一个实例。这是一项要求。
我可以使用
.语法代替::。但这是个人风格。
现在的问题是,这个解决方案有什么缺点吗?我觉得我在做 C++ 不应该做的事情,因为 Visual Studio 的 IntelliSense 一直在吓坏我,并认为 my_project::Foo 没有被声明。可能是因为对象和类都被称为Foo,即使它们位于不同的命名空间中?
解决方案编译良好。我只是担心一旦我的项目规模变大,我可能会开始出现名称歧义。此外,我创建这个库的对象是否浪费了额外的内存?
我应该坚持使用singleton design pattern 作为替代解决方案吗?有其他解决方案吗?
更新:
在查看了所提供的解决方案并在 google 上搜索各种解决方案后,我偶然发现了extern。我不得不说我对这个关键字的真正作用有点模糊。自从我学习 C++ 以来,我一直对此感到困惑。但是在调整了我的代码之后,我把它改成了这样:
// Foo.h
namespace my_project
{
namespace library
{
class Foo_lib
{
public:
int some_value;
Foo_lib() { /* initialize library */ }
void bar() { /* do stuff */ }
private:
// restrict copy/assignment
Foo_lib(const Foo_lib&);
void operator=(const Foo_lib&);
};
} // library namespace
extern library::Foo_lib Foo;
} // my_project namespace
// Foo.cpp
#include "Foo.h"
namespace my_project
{
namespace library
{
// Foo_lib definitions
} // library namespace
library::Foo_lib Foo;
} // my_project namespace
// main.cpp
#include "Foo.h"
using namespace my_project;
int main()
{
int i = Foo.some_value;
Foo.bar();
int j = Foo.some_value;
return 0;
}
这似乎与之前的效果完全相同。但正如我所说,由于我对 extern 的使用仍然很模糊,这是否也会产生完全相同的不良副作用?
【问题讨论】:
-
不,这里不需要单例。你为什么要这样做?
-
@R.MartinhoFernandes:因为库在使用前需要初始化到某个状态。并且用户不应该负责初始化它。
-
@teedayf: 如果他们自己想在静态初始化期间使用它会发生什么?
标签: c++ visual-studio-2010 namespaces