声明某事与定义某事不同。有时候你可以同时做两个事情,但是你需要同时声明和定义一些事情。
为什么?
那么,因为标准这么说,但标准为什么这么说呢?
它与编译和链接工作的方式有关。如果我有几个源文件,a.cpp
和b.cpp
和几个头文件,a.h
和b.h
然后我想编译它们。一般来说,您可以单独编译所有源文件以获得a.o
和b.o
,然后将它们链接在一起以获得最终的程序。
说我们有:
// a.h =========================
class A { static int n; };
// b.h =========================
class B { static int n; };
// a.cpp =======================
#include "a.h"
#include "b.h"
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int bar() { return A::n - B::n; }
请记住,#include
基本上只是贴了包括文件中的其他文件。因此,所有的编译器看到,当我们编译a.cpp
和b.cpp
是:
// a.cpp =======================
class A { static int n; };
class B { static int n; };
int foo() { return A::n + B::n; }
// b.cpp =======================
class A { static int n; };
class B { static int n; };
int bar() { return A::n - B::n; }
哪个对象文件应该A::n
和B::n
进去? a.o
或b.o
?它在a.cpp
和b.cpp
中声明,所以编译器不知道该把它放在哪里。如果你把它放在两个地方,那么你会定义它两次,编译器将不知道要使用哪个(在这种情况下,链接器会给你一个'多重定义的符号'错误)。
这就是为什么我们需要一个定义。该定义告诉我们哪个对象文件将其放入。
// a.cpp =======================
#include "a.h"
#include "b.h"
int A::n = 0; // A::n goes in a.o
int foo() { return A::n + B::n; }
// b.cpp =======================
#include "a.h"
#include "b.h"
int B::n = 0; // B::n goes in b.o
int bar() { return A::n - B::n; }
值得指出的是,你可以在b.cpp
已经把无论是在a.cpp
或两者兼而有之。没关系,只要定义一次。
因为这就是语言所需。 –
[C++静态成员变量及其初始化]的可能重复(http://stackoverflow.com/questions/4547660/c-static-member-variable-and-its-initialization) –