【发布时间】:2011-09-11 13:54:07
【问题描述】:
在我声明的标题中
#ifndef SOUND_CORE
#define SOUND_CORE
static SoundEngine soundEngine;
...
但是 SoundEngine 的构造函数被多次调用,这怎么可能,当它被声明为全局静态时
我称之为
#include "SoundCore.h"
直接使用
soundEngine.foo()
谢谢
【问题讨论】:
在我声明的标题中
#ifndef SOUND_CORE
#define SOUND_CORE
static SoundEngine soundEngine;
...
但是 SoundEngine 的构造函数被多次调用,这怎么可能,当它被声明为全局静态时
我称之为
#include "SoundCore.h"
直接使用
soundEngine.foo()
谢谢
【问题讨论】:
我会使用extern 而不是静态的。这就是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();
}
【讨论】:
会为包含标头的每个翻译单元创建在标头文件中声明的静态变量的副本。
永远不要在头文件中声明静态变量。
您可以使用singleton 对象。
【讨论】:
extern 对象都有问题(无论是从设计的角度来看,还是从它们在 C++ 中的工作方式来看)。我的首选方法是在函数内实例化对象(main() 或调用链中类似的高级对象),并将引用(或可能是智能指针,取决于对象的生命周期的复杂程度)传递给需要的所有内容它。
正如其他人在答案中提到的那样,头文件中的static 变量包含在包含头文件的每个文件中。如果您仍想保留 static 并避免多次实例化,请将其包装在 struct 中。
//SoundCore.h
struct Wrap {
static SoundEngine soundEngine;
};
现在在.cpp 文件之一中定义此变量。
//SoundCore.cpp
SoundEngine Wrap::soundEngine;
并简单地使用它,
Wrap::soundEngine.foo();
【讨论】:
extern?
extern 是此类单个变量的最佳主意。由于@rubenvb 已经提出了相同的建议;我给了这个另一种方式(说if you still want to keep it static)。
static 关键字之外,您不会以任何方式“保持静态”,这在此上下文中具有不同的含义。这完全等同于将其设置为extern(即,它将链接从内部更改为外部),但是由于引入了无意义的类而导致了额外的混乱。
如果您将此头文件包含在多个文件中,您的类将针对每个包含进行实例化。我认为你最好看看单例模式,只获取 1 个实例,即只有一个构造函数调用。
【讨论】:
与许多其他保留字一样,static 是一个修饰符,根据上下文具有不同的含义。
在这种情况下,您正在创建一个 SoundEngine 类的对象,该对象在此模块中是私有的。这意味着它在其他模块中不可见。
但是,您将此行放在标题中,因此它是各个模块中的私有对象。我猜这就是构造函数被多次调用的原因。
【讨论】: