C++,静态 vs. 命名空间 vs. 单例

2022-01-05 00:00:00 static namespaces singleton c++

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

I already read a lot of posts and articles all over the net, but I couldn't find a definite answer about this.

我有一些具有类似目的的函数,我想在全局范围之外使用它们.其中一些需要是公开的,其他的应该是私有的(因为它们只是公共"函数的辅助函数).此外,我不仅有函数,还有变量.只有私有"辅助函数需要它们,而且它们也应该是私有的.

I have some functions with similar purposes that I want to have out of the global scope. Some of them need to be public, others should be private (because they are only helper functions for the "public" ones). Additionally, I don't have only functions, but also variables. They are only needed by the "private" helper functions and should be private, too.

现在有三种方式:

  • 创建一个所有东西都是静态的类(相反:潜在的不能在没有对象的情况下调用成员函数"――并非所有东西都需要是静态的)
  • 创建一个单例类(相反:我需要这个对象)
  • 创建一个命名空间(没有私有关键字――我为什么要把它放在一个命名空间中呢?)

我该怎么做?结合其中一些方式的可能方式?

What would be the way to take for me? Possible way of combining some of these ways?

我想到了类似的东西:

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

谢谢.

推荐答案

如前所述,使用全局变量通常是不好的工程实践,除非绝对需要(例如映射硬件,但这种情况并不经常发生).

As noted, using global variables is generally bad engineering practice, unless absolutely needed of course (mapping hardware for example, but that doesn't happen THAT often).

在类中存储所有内容是您在类 Java 语言中会做的事情,但在 C++ 中您不必这样做,事实上,在这里使用名称空间是一个更好的选择,如果只是:

Stashing everything in a class is something you would do in a Java-like language, but in C++ you don't have to, and in fact using namespaces here is a superior alternative, if only:

  • 因为人们不会突然构建您的对象的实例:目的是什么?
  • 因为没有为命名空间生成内省信息 (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 和编译时优势!)

The anonymous namespace neatly tucked in a source file is an enhanced private section: not only the client cannot use what's inside, but he does not even see it at all (since it's in the source file) and thus do not depend on it (which has definite ABI and compile-time advantages!)

相关文章