class 没有实例数据,或者子命名空间中的命名空间 + 全局变量?

class without instance data, or namespace + globals in a sub-namespace?

我有几个相关的方法,都使用了一些全局数据(*),而且都是在header中实现的。我应该...

这两个选项对我来说似乎有点难看,但我想知道其中一个是否具有我所缺少的有条不紊的好处,这应该让我更喜欢它。我可以尝试向后弯曲并将互斥量移动到 .cpp 文件中,因此这可能是第三种选择,但它不会很漂亮...


(*) - 在我的特定情况下它是一个互斥量。

从一般"good practice"的角度来看,我会避免任何全局数据,并尽可能少地使用静态数据(避免单例综合症)。

第一个问题是:拥有这些对象的多个副本是否有害?通常,如果您不管理硬件访问或类似的东西,它就不会。即使您应该只使用一个,也最好使其尽可能通用,并允许 class.

的多个实例

此外,静态/全局变量往往会带来 threads/processes 的问题,因为有时很难计算出您拥有多少个静态对象副本。

所以作为一个简短的回答:把它们放在 class 中,作为非静态的,并将那些 "global" 数据也放入 class 中。

如果产生这些数据的原因是多线程或多进程,那么从设计的角度来看可能有问题。

如果您没有选择更合适的解决方案,那么我会使用命名空间:class 使用全局参数会破坏任何程序员期望从您的代码中获得的封装原则。

已编辑:

在问题的版本之后并试图更接近问题是什么:

假设您需要一个互斥锁的包装器,每个进程都是唯一的。

class MyMutexWrapper // very minimal class, you should finish it.
{
    MyMutex mutex;
public:
    anyFunction();
};

一旦你有了这个,你可以创建它的一个全局实例并在整个代码中共享它。更好的解决方案仍然是在任何范围内创建它并将它传递给任何使用它的组件。 例如,您可以传递参考。

这种方法可能看起来更复杂,但它避免了交叉依赖并使您的代码结构更清晰 => 然后您可以重用它、扩展它、维护它...

在这里使用 class 的唯一额外好处是,如果有人使用该互斥体(当然,如果您将其设为私有),编译器会发出警告。

但是,在这两种情况下,您只能在header中声明数据,并且您仍然必须在某个翻译单元中只定义一次。我建议您放弃 in-header 实现,并在同一个翻译单元中隐藏静态互斥锁和函数实现。

从那时起,您可以使用命名空间,因为它只是一个组织问题。