C ++,静态与命名空间与单例

时间:2011-04-26 16:26:42

标签: c++ static namespaces singleton

我已经在网上阅读了很多帖子和文章,但我找不到明确的答案。

我有一些具有类似目的的功能,我想要超出全局范围。其中一些需要是公开的,其他应该是私有的(因为它们只是“公共”的辅助函数)。 另外,我不仅有函数,还有变量。它们只需要“私人”辅助函数,也应该是私有函数。

现在有三种方式:

  • 创建一个静态的类(反对:潜在的“无法调用没有对象的成员函数” - 并非一切都需要是静态的)
  • 制作单身课程(反对:我将需要该对象)
  • 创建一个名称空间(没有私有关键字 - 为什么我要把它放在名称空间中呢?)

给我带来什么方式?结合其中一些方法的可能方法?

我想到了类似的东西:

  1. 制作单例,静态函数使用单例对象的辅助函数(这可能吗?我仍然在类中,但是访问它的类型的对象)
  2. 在程序启动时调用
  3. 构造函数,初始化所有内容( - >确保静态可以访问单例对象中的函数)
  4. 仅通过MyClass :: PublicStaticFunction()
  5. 访问公共函数

    感谢。

6 个答案:

答案 0 :(得分:29)

如上所述,使用全局变量通常是糟糕的工程实践,除非当然绝对需要(例如映射硬件,但这种情况经常不会发生)。

将类中的所有东西存放在类似Java的语言中,但是在C ++中你不必这样做,事实上在这里使用命名空间是一个更好的选择,如果只是:

  • 因为人们不会突然构建你的对象的实例:到底是什么?
  • 因为没有为名称空间生成内省信息(RTTI)

这是一个典型的实现:

// foo.h
#ifndef MYPROJECT_FOO_H_INCLUDED
#define MYPROJECT_FOO_H_INCLUDED

namespace myproject {
  void foo();
  void foomore();
}

#endif // MYPROJECT_FOO_H_INCLUDED

// foo.cpp
#include "myproject/foo.h"

namespace myproject {

namespace {
  typedef XXXX MyHelperType;

  void bar(MyHelperType& helper);
} // anonymous

void foo() {
  MyHelperType helper = /**/;
  bar(helper);
}

void foomore() {
  MyHelperType helper = /**/;
  bar(helper);
  bar(helper);
}
} // myproject

整齐地隐藏在源文件中的匿名命名空间是一个增强的private部分:不仅客户端不能使用内部的内容,而且他甚至根本看不到它(因为它在源文件中)因此不依赖它(具有明确的ABI和编译时优势!)

答案 1 :(得分:7)

Don't make it a singleton

对于不直接依赖这些变量的公共帮助函数,请将它们设为非成员函数。把它们放在课堂上没有任何好处。

对于其余的,将它作为普通的非静态成员放在一个类中。如果您需要一个全局可访问的类实例,那么创建一个(但不要使它成为单例,只是全局)。

否则,在需要时将其实例化。

答案 2 :(得分:2)

这样做的经典C方法,似乎就是你想要的,是将公共函数声明放在头文件中,并将所有实现放在源文件中,使变量和非公共函数保持静态。否则只是把它作为一个班级来实现 - 我想你在这里从一个小山丘做了一点山。

答案 3 :(得分:1)

如何在全球范围内使用关键字static(将文件本地化的内容)作为隐私替代品?

答案 4 :(得分:1)

从你的描述中看起来你在这里有相互交互的方法和数据,换句话说,它听起来像你真的想要一个非单例类来维持状态并在该状态下提供操作。将您的公共函数公开为接口,并将其他所有内容保密。

然后,您可以根据需要创建实例,您不必担心初始化顺序或线程问题(如果每个线程有一个),并且只有需要访问权限的客户端才有一个操作对象。如果您真的需要其中一个用于整个程序,那么您可以放弃使用main或可能instance方法设置的全局指针,但这些指针会带来各自的问题。

答案 5 :(得分:0)

请记住,单例类的单例实例是一个有效的实例,因此它完全能够成为非静态成员函数的接收者。如果您将单件工厂作为静态函数公开,那么将所有公共功能作为公共非静态成员函数和私有功能作为私有非静态成员函数,任何可以进入类的人都可以通过简单地调用单例工厂来访问公共功能功能

您没有描述您尝试包装的所有功能是否与证明在同一个类中相关,但如果是,则此方法可能有效。

如果采用“类C”方法并且只使用顶级函数,则可以通过在.cpp文件中声明它们而不是公开包含的.h文件将它们设为私有。如果采用这种方法,您还应该使它们成为静态(或使用匿名命名空间)。