静态类成员无法识别,但仅适用于新版本的 C++ 编译

Soh*_* Si 2 c++ clang c++14

static_member以下代码中无法识别静态类成员。

但是,它适用于旧版本的编译器。我使用的编译器是基于clang.

class my_class {
  public:
    static int static_member;
};

int main() {
  my_class::static_member = 0;
}
Run Code Online (Sandbox Code Playgroud)

要重现该错误,请将以上文件另存为c1.cpp并运行:

VER_TAG=latest # or VER_TAG=3.1.8

docker run --rm -v $(pwd):/src emscripten/emsdk::$VER_TAG emcc /src/c1.cpp
Run Code Online (Sandbox Code Playgroud)

导致错误:

wasm-ld:错误:/tmp/emscripten_temp_o3wmmq8k/c1_0.o:未定义符号:my_class::static_member

但是,如果我使用 VER_TAG=2.0.22(编译器的早期版本),它工作得很好。

我的代码有什么问题吗?还是与编译器实现有关?

use*_*570 8

来自静态数据成员定义的文档

类体内的声明不是定义,并且可以将成员声明为不完整类型(void 除外),包括声明该成员的类型。

因此,我们必须首先为静态数据成员提供类外定义,如下所示:

class my_class {
  public:
    static int static_member;//this is a declaration
};
int my_class::static_member = 0;//this is a definition
int main() {
 std::cout<<my_class::static_member<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

从 C++17 开始,我们可以使用inline关键字,这样我们就不再需要静态数据成员的类外定义:

class my_class {
  public:
    inline static int static_member = 0;  // this is a definition
};

//nothing needed here

int main() {
  std::cout<<my_class::static_member; // use the static_member here
}
Run Code Online (Sandbox Code Playgroud)

  • 我因提及“内联”而投票。我往往会忘记那个版本:-) (3认同)

Ted*_*gmo 5

我的代码有什么问题吗?

是的,你的static_member没有定义。

class my_class {
  public:
    static int static_member;  // declaration
};

int my_class::static_member{}; // missing definition

int main() {
  my_class::static_member = 0; // now you can use it here
}
Run Code Online (Sandbox Code Playgroud)

  • @SohailSi我认为你的旧链接器有一个缺陷,没有检测到这个丢失的定义 - 或者编译器可能出于某种原因自行添加了一个定义。 (2认同)