C++中的静态类

4
在头部声明中:
#ifndef SOUND_CORE
#define SOUND_CORE

static SoundEngine soundEngine;

...

但是 SoundEngine 的构造函数被调用了多次,这怎么可能呢?它被声明为全局静态的。

我是这样调用它的:

#include "SoundCore.h"

并直接使用它

soundEngine.foo()

谢谢你

5个回答

7
每当您包含头文件时,静态变量的副本会为每个翻译单元创建。
永远不要在头文件中声明您的静态变量。
您可以使用单例对象。

1
@Mario The Spoon:是的,您可以这样做,而且这是完全有效的,也会起作用,但出于个人选择的原因,我真的不喜欢以那种方式使用extern。 - Alok Save
1
单例和extern对象都存在问题(从设计角度和C++工作方式两方面考虑)。我的首选方法是在函数内实例化对象(如main()或类似的高层调用链),并将引用(或可能是智能指针,取决于对象生命周期的复杂性)传递给所有需要它的对象。 - Mike Seymour
@Mike,@Als:如果应用程序需要一个真正的全局配置/存储对象,为什么不将其设置为全局变量(在命名空间内)?我唯一能看到的问题是线程安全,但可以通过使用正确的线程编程习惯来解决,这些习惯可以在对象外部强制执行,或者隐藏在全局/静态对象内部。 - rubenvb
@Mike Seymour:没错,但如果调用链太长,就可能被迫使用globalstatic单例全局静态各有其优缺点,选择哪种方式需要仔细考虑。 - Alok Save
@Mike Seymour:所谓“太长”,是指通过太多实际上并不需要使用它的函数传递变量,这也增加了在这个漫长的流程中无意中修改变量的风险。 - Alok Save
显示剩余8条评论

7
我会使用 extern 而不是static。这就是 extern 的作用。
在头文件中:
extern SoundEngine soundEngine;

在一个相关的源文件中:

SoundEngine soundEngine;

这将创建一个包含实例的翻译单元,包含头文件将使您能够在代码的任何地方使用它。
// A.cpp
#include <iostream>
// other includes here
...
extern int hours; // this is declared globally in B.cpp

int foo()
{
hours = 1;
}


// B.cpp
#include <iostream>
// other includes here
...
int hours; // here we declare the object WITHOUT extern
extern void foo(); // extern is optional on this line

int main()
{
foo();
}

2
正如其他回答中提到的那样,头文件中的 static 变量会被包含在每个包含该头文件的文件中。如果您仍然希望保持它的 static 特性并避免多次实例化,则可以将其包装在一个 struct 中。
//SoundCore.h
struct Wrap {
  static SoundEngine soundEngine;
};

在其中一个.cpp文件中定义此变量。
//SoundCore.cpp
SoundEngine Wrap::soundEngine;

并且简单地使用它,如下所示:

Wrap::soundEngine.foo();

为什么你想要将它封装在一个类中而不是在命名空间范围声明为extern - Mike Seymour
1
@Mike,实际上extern是这种单变量的最佳选择。由于@rubenvb已经提出了相同的建议,我给出了另一种方式(说“如果你仍然想保持它静态”)。 - iammilind
除了保留“static”关键字外,您在任何方面都没有“保持静态”,在此上下文中,“static”关键字具有不同的含义。这与使其“extern”(即将链接从内部更改为外部)完全相同,但是由于引入了一个无意义的类而导致了额外的混淆。 - Mike Seymour

0
如果您在多个文件中包含此头文件,则会为每个包含实例化您的类。我认为您最好看一下单例模式,以获取仅1个实例,即仅一个构造函数调用。

0

像许多其他保留字一样,静态是一个修饰符,根据上下文具有不同的含义。

在这种情况下,您正在创建一个类SoundEngine的对象,该对象在此模块中是私有的。这意味着其他模块无法看到它。

但是,您将此行放在标题中,因此它是各种模块中的私有对象。我猜这就是构造函数被多次调用的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接