我们都知道类的静态成员变量必须在类外初始化,不仅如此,类的静态成员变量最好在源文件中初始化,而不能在头文件初始化,否则,编译的时候就会报错"symbol multiply defined".
举例:
/*--testA.h--*/
class A
{
public:
void testB();
private:
struct B
{
int getStatic();
void addStatic();
static int seq; //static member variable
int num;
};
//int A::B::seq = 0; //error, must be defined in cpp file
};
//int A::B::seq = 0; //error, must be defined in cpp file
#include "test30-static-member.h"
void A::testB() {
B b[2];
b[0].addStatic();
std::cout << b[0].getStatic() << std::endl;
b[1].addStatic();
std::cout << b[1].getStatic() << std::endl;
}
int A::B::seq = 0; //right
/*--main.cpp--*/
#include "testA.h"
//int A::B::seq = 0; //also work
int main()
{
A a;
a.testB();
return 0;
}
输出:
1
2
C++中有声明(declare)和定义(define)的概念,int A::B::seq = 0;
与其叫做初始化,叫做定义更准确, 而结构体中的这句话实际为声明。
C++中的所有变量、函数、类等都只能定义一次,可以声明多次。 如果把int A::B::seq = 0;
放到头文件中,头文件被多次include, 则可能会导致变量被多次声明, 因此不可行。
??
declare: 编译期告诉编译器变量的名字和类型
define: 链接的时候告诉变量存放位置,函数实体等。
??
根据评论提醒,static const的成员变量可以在类内初始化, 但仅限于整型和enum型。
总结:
In C++11, non-static data members, static constexpr data members, and static const data members of integral or enumeration type may be initialized in the class declaration.
struct X {
int i=5; // ok
const float f=3.12f; // ok
static const int j=42; // ok
static constexpr float g=9.5f; //ok
static const double d = 1.23; // error
static const char* cstr = "FOO"; // error
struct FooT { int i; };
static const FooT foo; // ok
};
https://stackoverflow.com/questions/9141950/initializing-const-member-within-class-declaration-in-c
https://stackoverflow.com/questions/19575258/why-must-non-integral-static-data-members-initialized-in-the-class-be-constexpr
One of the reasons why this was the case prior to C++11’s addition of constexpr was the standard did not specify how floating points were to be implemented (it is left to the processor/architecture - for example, when you say float x = 1.6f, it is actually 1.6000000000024 on most systems).