0
  class X {
       static int i;
       // some other function, variable declaration, cons, dest
  };

  int X :: i ; **(!)** 

为什么我必须写那(!)行,总是?

如果我不写,编译器无法完成内部链接,所以它给出(我假设)链接器错误。为什么 ?

4

7 回答 7

1

因为这就是静态成员的工作方式。它们除了直接存在于类中的实例之外。

您不能在类中定义它们,因为那样的话,每个使用您的类的实现文件都会有多个定义。

因此,您需要选择一个实际定义静态成员的实现文件。

于 2011-02-10T12:45:52.313 回答
1

这被称为单一定义规则。每个全局对象(技术上,每个具有外部链接的对象)都必须在一个源文件中定义(技术上,在一个翻译单元中)。但是,它可以声明任意多次。

通常,类定义将位于头文件中,该文件可能包含在许多源文件中。所以不能在那里定义任何静态成员只能声明,否则会有多个定义。您必须在一个源文件中单独定义静态成员,以便链接器准确找到一个定义。这就是标记的行的(!)作用。

于 2011-02-10T12:48:27.240 回答
0

静态变量必须在 TU(即 cpp 文件)中定义(与声明相反)。

如果它只是声明而不定义,则不会为其分配存储空间,因此链接器无法找到它。

于 2011-02-10T12:47:50.010 回答
0

static int i;是一个声明,即告诉编译器在某些翻译单元(=>.cpp文件)中将实际定义这样的静态字段。需要让编译器知道存在这样的变量,并让您在声明它的每个翻译单元中使用它。

int X :: i;相反,它是一个定义,它告诉编译器实际为该变量提供空间。它必须保留在一个 中.cpp,否则每个翻译单元都会为它自己提供一些空间(并且链接器会抱怨)。

extern这与为什么对于全局变量,您需要在每个需要使用它的文件中声明(通常放在头文件中)并在定义它的单个文件中进行正常定义的原因完全相同.cpp

于 2011-02-10T12:49:32.503 回答
0

C++ 明确区分了声明和定义。你需要告诉编译器两件事:

  1. 变量的数据类型:声明。
  2. 您希望变量所在的内存位置:定义。

这通常一步完成,即一个局部 int 变量:

void f() {
    int x; // Declaration and definition.
}

由于 .hpp 头文件可以包含在许多 .cpp 文件中,因此您的(!)行必须驻留在单个特定的 .cpp 上,通常在任何头文件之外。

于 2011-02-10T12:49:56.390 回答
0

静态类成员在所有类实例之间共享(在内存中只有一个位置存在此类变量),因此static int i;在类声明中仅表示变量声明-您需要在某处为该变量分配内存-您需要定义它-这是在实现文件中完成的int X::i;

于 2011-02-10T12:51:34.623 回答
0

类定义只定义成员,但它必须存在于单个编译单元(即.cpp 文件)中。

您可以说它是“单一定义规则”的一部分。

于 2011-02-10T12:51:41.443 回答