我有类声明(.h文件),如下所示:
struct MyClass {
static const uint32_t SIZE = sizeof(MyType);
};
将我的程序链接在一起时,我会收到MyClass::SIZE
的链接器错误。 nm
确认符号未定义。 http://forums.devshed.com/c-programming-42/linker-errors-undefined-reference-to-static-member-data-193010.html似乎解决了我的问题,表明“类静态对象也必须在普通全局变量之外的任何函数或类之外声明。”
我有两个问题:
答案 0 :(得分:5)
您的问题可能与获取变量地址的人无关。它可能只是编译器选择不使用变量作为常量表达式,即使它可以。例如:
f(int const&);
struct X { enum { enum_val = 42 }; static int const static_mem = 42; };
f(5);
f(X::enum_val);
f(X::static_mem);
在前两种情况下,编译器需要将输入用作常量表达式,const&
可以用这样的方式初始化。然而最后一种情况则不同。即使您的意图可能是使用static_mem
作为常量表达式,并且它完全合法,编译器也可以自由地执行,有些实际上会创建对变量本身的引用。这是变量的“使用”,因此您需要在程序中的某个位置定义该变量。
有两种方法可以解决这个问题:
1)为您的程序添加定义。
2)使用枚举代替: 结构X. { 枚举{static_mem =? }; };
如果您确实想要获取变量的地址,那么第一个解决方案是必要的。有可能你没有,或者你已经创建了那个定义。后面的解决方案强制编译器使用X::static_mem
作为常量表达式,因为枚举成员实际上并不作为程序中的对象存在。根据您在问题中的最后陈述,我认为这是您真正想要的解决方案。
答案 1 :(得分:2)
标准要求静态成员积分常量的定义仅在其地址被采用时,否则使用初始化器(您拥有的)的声明就足够了。该链接器错误消息应该提到哪个对象/函数的地址为MyClass::SIZE
。
答案 2 :(得分:0)
如果你要这样做:
//.h file
struct MyClass
{
static const uint32_t SIZE = sizeof(MyType); //this is declaration!
};
//.cpp file
const uint32_t MyClass::SIZE; //this is definition - necessary!
答案 3 :(得分:0)
从No definition available for static const member with initializer?
引用自己的话从9.4.2 / 4:
如果静态数据成员是const 整数或常数枚举类型, 它在课堂上的宣言 定义可以指定一个 常数初始化器应该是一个 积分常数表达式(5.19)。 在这种情况下,该成员可以出现在 内积分常数表达式 它的范围。 会员仍然是 如果是,则在命名空间范围内定义 在程序中使用和命名空间 范围定义不得包含 初始化程序。
根据这些参考文献,我们可以推断(“......仍然应该在9.4.2 / 4中定义......”)如果没有定义那么程序就没有格式良好。
@DavidRodríguez - dribeas指出你必须在某个地方获取程序中静态成员的地址。如果你可以避免使用地址,那么就不需要在实现文件中定义(或者你没有获取地址并且有一个错误的编译器)。否则你必须有定义。
答案 4 :(得分:-1)
最有可能,但没有任何错误消息,很难说。
使用静态const int。您可以在标题中初始化它,而不需要在cpp中声明它。