【问题标题】:Can I initialize a static member from within another function?我可以从另一个函数中初始化静态成员吗​​?
【发布时间】:2013-06-25 20:18:52
【问题描述】:

struct 中有一个静态成员,因为在析构函数中需要它。

struct Form
{
    // ...
    ~Form()
    {
        // access World here
    }
    static btDynamicsWorld *World;
};

有没有办法在另一个函数中初始化这个静态成员?

void ModulePhysics::Init()
{
    // ...
    btDynamicsWorld *Form::World = /* ... */;
}

我当前的代码导致这两个编译器错误。

错误 1 ​​错误 C2655: 'Form::World' : 在当前范围内定义或重新声明非法

错误 2 错误 C2086: 'btDynamicsWorld *Form::World' : 重新定义

【问题讨论】:

  • 你确定,静态成员是你想要的吗?该类的每个实例都是相同的!
  • @Sebastian struct 表示物理模拟中的刚体。 World 代表了许多物体之间物理相互作用的空间,只有一个实例存在。尸体必须在破坏时从世界中移除,否则模拟会崩溃。如果有更好的方法来处理这个问题,我很乐意听到。
  • 您知道在结构中声明一个静态变量不会为它保留任何 RAM,您需要在其他地方再次声明它的 RAM 对吗?
  • @danijar: 如果这个“世界”没有直接连接到“表单”类,将它作为一个简单的全局变量(静态的,或在命名空间中,或单身人士)
  • 似乎拥有一个包含大量 body 对象的 World 对象可能会更好。

标签: c++ static scope initialization member


【解决方案1】:

不,你不能。但是你可以将它初始化为NULL,在函数中,如果是NULL,进行真正的初始化。

编辑:举个例子:

void ModulePhysics::Init()
{
    // ...
    if(Form::World == NULL)
    {
        // The real initialization
    }
}

文件范围内的某个地方(在 C 文件中,而不是在标题中!):

btDynamicsWorld* Form::World = NULL;

【讨论】:

  • 那太好了,您能提供一个简短的代码示例吗?
  • 非常感谢。它现在编译。我需要在每个源文件(包括结构)中初始化静态成员吗​​?
  • 没有。必须在一个文件中定义,不能在多个文件中定义(一个定义规则,ODR)
  • 很高兴听到!那么值是在所有源文件之间共享的吗?
  • 是的。它在所有源文件之间共享。与文件范围静态变量不同。
【解决方案2】:

不,你不能。

类成员列表中静态数据成员的声明不是定义。您必须在类声明之外定义静态成员,在命名空间范围内。

Here 您可以获得有关如何以及在何处初始化静态类变量的更详细说明。

【讨论】:

    【解决方案3】:

    在init()方法中去掉静态变量前面的类型。

    希望它能解决你的问题。

    【讨论】:

    • 我之前尝试过,但它会引发 unresolved external symbol 链接器错误。
    【解决方案4】:

    1) 所有静态类成员(除了在类定义中立即初始化的整数成员)也应该在外部定义(最好在 .cpp 文件中,以便编译器只处理一次定义)。例如:

    // form.h
    struct Form
    {
        static btDynamicsWorld *World;
    };
    
    
    // form.cpp
    
    // You can initialize World here as well if you want to,
    // but you don't have to, as long as it's not const.
    // However, it is generally a good idea to initialize
    // pointers to NULL (or nullptr in C++11).
    btDynamicsWorld *Form::World;
    

    这只能在全局范围内完成。如果你不这样做,如果你尝试引用这个变量,你会得到链接器错误(未定义的符号)。

    2)您似乎想要做的不是“初始化”,而是分配给静态成员。你做的几乎是正确的,但你不需要重新声明类型:

    void ModulePhysics::Init()
    {
        Form::World = /* ... */;
    }
    

    3) 我真的不明白为什么需要将任何东西设为静态才能从析构函数中访问它。析构函数负责删除实例变量,但是当析构函数的主体执行时它们还没有被删除。所以你也可以使用“普通”类成员,除非你打算在不同的类实例之间共享它的值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多