C++类const静态成员初始化报不完整类型、未定义引用错误求解
错误原因
两个编译错误的本质都是C++静态类成员的语法规则限制:
- 第一个错误
invalid use of incomplete type 'class Move':C++标准规定,类的完整定义要到类体的闭合花括号}处才生效。你在类内部写const static Move NONE = Move(0,-1);时,Move还是不完整类型,编译器此时无法实例化Move对象完成初始化,因此报错。 - 第二个错误
undefined reference to Move::NONE:类内写的const static Move NONE;只是静态成员的声明,不是定义。C++的静态成员变量不属于某个具体对象,是类全局共享的,必须在类外单独定义分配内存,你没有在实现文件中给出该成员的定义,链接阶段找不到对应实体就会报未定义引用。
修复方案
兼容所有C++标准的通用写法
- 修改头文件
move.hpp,去掉静态成员的类内初始化,仅保留声明:
class Move { public: Move(); Move(int, int); public: int from; int to; const static Move NONE; };
- 在实现文件
move.cpp中,添加静态成员的类外定义和初始化:
#include "move.hpp" Move::Move() { this->from = 0; this->to = 0; } Move::Move(int from, int to) { this->from = from; this->to = to; } // 静态成员类外定义 const Move Move::NONE = Move(0, -1);
main.cpp不需要任何修改,重新编译即可正常运行,输出结果为:
0 -1
C++17及以上版本简化写法
如果编译时开启C++17及以上标准支持(GCC 7+版本可在Code::Blocks编译选项中添加-std=c++17开启),可以用inline修饰静态成员,直接在类内完成初始化,不需要额外在cpp中写定义:
class Move { public: Move(); Move(int, int); public: int from; int to; inline const static Move NONE = Move(0,-1); };
inline修饰的静态成员会在类定义完成后再处理初始化逻辑,不会触发不完整类型错误,同时编译器会自动处理静态成员的定义,不会出现链接报错。
内容的提问来源于stack exchange,提问作者le Mandarin
相关产品推荐
相关产品推荐

