【问题标题】:Initializing a static class member [duplicate]初始化静态类成员[重复]
【发布时间】:2013-07-12 20:43:33
【问题描述】:

我正在尝试初始化一个静态类成员并且没有运气。这是一个测试:

文件测试.h

#include <string>

class Test {

public:
    static void init(char*);

private:
    static std::string  *sp;

};

文件Test.cpp

#include "Test.h"

// Initialize the class
void
Test::init(char *foo) {
    Test::sp = new std::string(foo);
}

int main(int argc, char** argv) {
    Test::init(argv[1]);  // call the class initializer
}

链接器失败:

Undefined symbols for architecture x86_64:
  "Test::sp", referenced from:
      Test::init(char*) in Test-OK13Ld.o
ld: symbol(s) not found for architecture x86_64

在现实世界中,init() 会做一些实际的工作来设置静态成员。有人能指出错误吗?

【问题讨论】:

  • static std::string *sp; 未定义。
  • 还有,为什么要使用指向 std::string 的指针?
  • 好吧,我知道未定义的 ref / unresolved extern 是什么,因此该链接相当广泛。 @itwasntpete 的评论提醒我,我所拥有的只是一份声明。所以显然我需要在类定义中(但在之外)定义。

标签: c++ class static initializer


【解决方案1】:

这是 C++ 的一个令人尴尬的“特性”:您需要手动操作以确保链接器可以生成符号。您需要选择 some cpp 文件,并确保不会在任何其他文件中对相同符号发生此类牵手(否则链接器会在遇到重复符号时失败)。因此,您必须在 cpp 文件中为您的类再次声明静态成员变量,如下所示:

std::string * Test::sp; // or sp = NULL;

【讨论】:

  • 啊——声明和定义的区别。我从没想过那些静电会在哪里。我只是想象 C++ 会处理事情。值得一提的是(如果这是真的!)定义(或者是另一个声明?)必须在 .cpp 文件中的任何函数之外。
  • 这真的丑!如果写成赋值语句,在什么时候执行?
  • 好吧,这就是“静态初始化顺序惨败”一词的丑陋之处。基本上,在 main 之前,但何时完全依赖于所有其他 static 变量,而你真的,真的不想依赖这个。所以不要在main 之前做毛茸茸的事情,如果你能避免的话(几乎总是这样)。将指针设置为NULL 的唯一要点是您可以检查它是否已被您的 init 函数“正确”设置。
  • 谢谢。如果您要编辑答案以强调静态成员定义应该在 .cpp 中的任何函数之外,我会给您打勾。 (我知道编译器会叫,但它确实看起来很奇怪。)
【解决方案2】:

正如错误消息所说,static std::string *sp; 必须在某处定义,因为它与 class Test 的任何实例都没有关联。

在全局范围内将其添加到 Test.cpp 将解决该问题:

std::string *Test::sp = NULL;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 2015-05-18
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多