繁体   English   中英

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

[英]C++, static vs. namespace vs. singleton

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

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

现在有以下三种方式:

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

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

我想到了这样的事情:

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

谢谢。

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

将所有内容存储在类中是您可以使用类 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 和编译时优势!)

不要让它成为单身人士

对于不直接依赖于这些变量的公共辅助函数,将它们设为非成员函数。 把它们放在一个班级里没有任何好处。

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

否则,在需要时实例化它。

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

在全局范围内使用关键字static (使文件本地化)作为隐私替代品怎么样?

从您的描述来看,您的方法和数据似乎在这里相互交互,换句话说,在我看来,您实际上想要一个非单例类来维护状态并提供对该状态的操作。 将您的公共函数作为接口公开,并保持其他一切私有。

然后您可以根据需要创建实例,您不必担心 init 顺序或线程问题(如果每个线程有一个),并且只有需要访问的客户端才会有一个对象可以操作。 如果你真的只需要其中一个来处理整个程序,你可以说一个在main设置的全局指针或可能是一个instance方法,但这些都有自己的问题。

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

您没有描述您尝试包装的所有功能是否与证明属于同一类的相关性一样相关,但如果是,这种方法可能会奏效。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM