7

my_test.h

#ifndef MY_TEST  
#define MY_TEST

struct obj {
  int x;
  int y;
};

class A {
private:
  const static int a=100;
  const static obj b;
};

const obj A::b={1,2};

#endif

使用此头文件编译 cpp 时,'multiple definition of 'A::b'会出现错误。

  1. 为什么我已经在使用警卫宏了?
  2. 为什么不A::a产生错误?(我不能写代码const static obj b={1,2}class A
4

4 回答 4

4

为什么我已经在使用警卫宏了?

标头保护仅防止在同一翻译单元中多次包含头文件内容,而不是跨多个翻译单元。

为什么是A::a没有错误信息(我不能写代码const static obj b={1,2}class A

编译器允许类内初始化作为 const 字面量类型的静态数据成员的特例。您的示例之一是类内初始化。

const A::b在包含标头的每个翻译单元中定义相同的符号名称,因此违反了一个定义规则

您需要将定义移动到一个且只有一个源 cpp 文件,以便它只定义一次。

于 2013-02-22T09:12:07.247 回答
1

Alok 已经回答了您的问题,但这里有一些简单的经验法则,以易于记忆的形式:

  1. 声明进入 .h 文件
  2. 定义在 .cpp 文件中

因此,静态成员需要在.h文件中声明,然后在.cpp文件中定义。在您的情况下,修复声明的语法,然后将它们移动到“my_test.cpp”文件。

于 2013-02-22T09:21:30.883 回答
0

问题是您的定义A::b不包含类型。要成为一个有效的定义,它应该是:

const obj A::b = {1, 2};

这将消除编译错误,但如果您在多个源文件中包含此头文件,您仍然会收到链接器错误,因为A::b那时将被多次定义。您应该将定义移动到 .cpp 文件中。

于 2013-02-22T09:09:02.497 回答
0

无论您是否有标头保护,将该初始化放在头文件中都意味着您将A::b在包含该头文件的每个源文件中获得一个实例。因此链接器错误。

所以,一般来说,这是可能的,但不是一个好主意。

于 2013-02-22T09:11:48.750 回答