前言:
在c++中我们可以使用 static 关键字来把类成员定义为静态的。当我们声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的。如果不存在其他的初始化语句,在创建第一个对象时,所有的静态数据都会被初始化为零。
在c++中,我们不能把静态成员放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化,如下面的实例所示。
#include <iostream>
using namespace std;
class Obj{
public:
// 声明类静态成员,这里不能对它进行初始化赋值
static int m_a;
};
// 初始化类静态成员(通过范围解析符::)
int Obj::m_a = 0;
int main(){
// 通过对象访问静态属性
Obj o;
o.m_a = 10;
cout << o.m_a << endl;
// 通过类访问静态属性
cout << Obj::m_a <<endl;
}
c++类模板遇到static
当类模板中出现static修饰的静态类成员的时候,我们只要按照正常理解就可以了。static的作用是将类的成员修饰成静态的,所谓的静态类成员就是指类的成员为类级别的,不需要实例化对象就可以使用,而且类的所有对象都共享同一个静态类成员,因为类静态成员是属于类而不是对象。那么,类模板的实现机制是通过二次编译原理实现的。c++编译器并不是在第一个编译类模板的时候就把所有可能出现的类型都分别编译出对应的类(太多组合了),而是在第一个编译的时候编译一部分,遇到泛型不会替换成具体的类型(这个时候编译器还不知道具体的类型),而是在第二次编译的时候再将泛型替换成具体的类型(这个时候编译器知道了具体的类型了)。由于类模板的二次编译原理再加上static关键字修饰的成员,当它们在一起的时候实际上一个类模板会被编译成多个具体类型的类,所以,不同类型的类模板对应的static成员也是不同的(不同的类),但相同类型的类模板的static成员是共享的(同一个类)。
#include <iostream>
using namespace std;
template<typename T>
class Obj{
public:
static T m_t;
};
template<typename T>
T Obj<T>::m_t = 0;
int main04(){
Obj<int> i1,i2,i3;
i1.m_t = 10;
i2.m_t++;
i3.m_t++;
cout << Obj<int>::m_t<<endl;
Obj<float> f1,f2,f3;
f1.m_t = 10;
f2.m_t++;
f3.m_t++;
cout << Obj<float>::m_t<<endl;
Obj<char> c1,c2,c3;
c1.m_t = 'a';
c2.m_t++;
c3.m_t++;
cout << Obj<char>::m_t<<endl;
}
运行结果:
12
12
c
可以看到相同类型如int对应的类模板的对象之间的static成员是共享的,不同类型之间如int,float,char对应的类模板的对象之间的static是不共享的。