【问题标题】:Static class in C++C++中的静态类
【发布时间】:2011-09-11 13:54:07
【问题描述】:

在我声明的标题中

#ifndef SOUND_CORE
#define SOUND_CORE

static SoundEngine soundEngine;

...

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

我称之为

#include "SoundCore.h"

直接使用

soundEngine.foo()

谢谢

【问题讨论】:

    标签: c++ class static


    【解决方案1】:

    我会使用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();
    }
    

    【讨论】:

      【解决方案2】:

      会为包含标头的每个翻译单元创建在标头文件中声明的静态变量的副本。
      永远不要在头文件中声明静态变量。

      您可以使用singleton 对象。

      【讨论】:

      • 是的,静态是每个翻译单元。补救措施是 Singleton 或类似的。
      • 愚蠢的我在想:你能不能做'extern SoundEngine soundEngine'然后在一个编译单元中实现为静态的(也就是说,没有extern关键字)?
      • @Mario The Spoon:是的,你可以这样做,而且它完全有效并且会起作用,但作为个人选择,我真的不喜欢以这种方式使用 extern。
      • 单例和extern 对象都有问题(无论是从设计的角度来看,还是从它们在 C++ 中的工作方式来看)。我的首选方法是在函数内实例化对象(main() 或调用链中类似的高级对象),并将引用(或可能是智能指针,取决于对象的生命周期的复杂程度)传递给需要的所有内容它。
      • @Mike, @Als:好吧,如果应用程序需要一个真正的全局配置/存储对象,为什么不将其设为全局(在命名空间内)?我能看到的唯一问题是线程,但这可以通过使用正确的线程习语来帮助,或者在对象外部强制执行,或者隐藏在全局/静态内部。
      【解决方案3】:

      正如其他人在答案中提到的那样,头文件中的static 变量包含在包含头文件的每个文件中。如果您仍想保留 static 并避免多次实例化,请将其包装在 struct 中。

      //SoundCore.h
      struct Wrap {
        static SoundEngine soundEngine;
      };
      

      现在在.cpp 文件之一中定义此变量。

      //SoundCore.cpp
      SoundEngine Wrap::soundEngine;
      

      并简单地使用它,

      Wrap::soundEngine.foo();
      

      【讨论】:

      • 为什么要将它包装在一个类中而不是在命名空间范围内声明它extern
      • @Mike,实际上extern 是此类单个变量的最佳主意。由于@rubenvb 已经提出了相同的建议;我给了这个另一种方式(说if you still want to keep it static)。
      • 除了保留 static 关键字之外,您不会以任何方式“保持静态”,这在此上下文中具有不同的含义。这完全等同于将其设置为extern(即,它将链接从内部更改为外部),但是由于引入了无意义的类而导致了额外的混乱。
      【解决方案4】:

      如果您将此头文件包含在多个文件中,您的类将针对每个包含进行实例化。我认为你最好看看单例模式,只获取 1 个实例,即只有一个构造函数调用。

      【讨论】:

        【解决方案5】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-09-26
          • 2011-01-17
          • 1970-01-01
          • 2014-01-22
          • 2012-03-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多