与任何其他类相同,类模板可以声明 static 成员:
template <typename T> class Foo { public: static std::size_t count() { return ctr; } void addctr() { ctr++; } void subctr() { ctr--; } private: static std::size_t ctr; // 下面可以有其他成员接口 }; template <typename T> std::size_t Foo<T>::ctr = 0; //定义并初始化 ctr
在这段代码中,Foo是一个模板类,它有一个名为 count 的 public static 成员函数和一个名为 ctr 的 private static 数据成员。每个 Foo 的实例都有自己的 static 成员实例。即,对任意给定类型X,都有一个Foo<X>::ctr 和一个 Foo<X>::count() 成员函数。所有 Foo<X>类型的对象共享相同的 ctr 对象和 count 函数。例如:
//实例化 static 成员 Foo<string>::ctr 和 Foo<string>::count Foo<string> fs; //所有三个对象共享相同的 Foo<int>::ctr 和 Foo<int>::count 成员 Foo<int> fi, fi2, fi3;
与任何其他 static 数据成员相同,模板类的每个static 数据成员必须有且仅有一个定义。但是,类模板的每个实例都有一个独有的 static 对象。因此,与定义模板的成员函数类似,我们将 static 数据成员也定义为模板:
template <typename T> std::size_t Foo<T>::ctr=0; //定义并初始化 ctr
与类模板的其他任何成员类似,定义的开始部分是模板的参数列表,随后是我们定义的成员的类型和名字。与往常一样,成员名包括成员的类名,对于从模板生成的类来说,类名包括模板实参。因此,当使用一个特定的模板参数类型实例化 Foo 时,将会为该类类型实例化一个独立的 ctr ,并将其初始化为 0。
与非模板类的静态成员相同,我们可以通过类类型对象来访问一个类模板的 static 成员,也可以使用作用域运算符直接访问成员。当然,为了通过类来直接访问 static 成员,我们必须引用一个特定的实例。
运行示例:
#include<iostream> #include<vector> #include<string> using namespace std; template <typename T> class Foo { public: static std::size_t count() { return ctr; } void addctr() { ctr++; } void subctr() { ctr--; } private: static std::size_t ctr; // 下面可以有其他成员接口 }; template <typename T> std::size_t Foo<T>::ctr = 0; //定义并初始化 ctr int main(int argc, char* argv[]) { Foo<int>fi; cout << "fi.count()=" << fi.count() << endl; fi.addctr(); Foo<int>fi2; fi2.addctr(); cout << "fi2.count()=" << fi2.count() << endl; cout << "fi.count()=" << fi.count() << endl; cout << "Foo<int>::count()=" << Foo<int>::count() << endl; Foo<double>fd; cout << "fd.count()=" << fd.count() << endl; return 0; }
运行结果:
S:ComputerTechVS2015hangSir_ProjConsoleConsoleDebug>template.exe fi.count()=0 fi2.count()=2 fi.count()=2 Foo<int>::count()=2 fd.count()=0
类似任何其他成员函数,一个 static 成员函数只有在使用时才会实例化。