对于某些特定类类型的全体对象而言,访问一个全局对象有时是有必要的。在程序运行的任意点可能需要统计已创建的特定类类型对象的数量,但是全局对象会破坏封装,并且没有安全保护,一般的用户代码就可以修改这个值。类可以定义 static 成员,用于解决同一个类的不同对象之间数据和函数共享的问题,用一个类的不同对象的的静态成员使用同一个内存空间。静态成员包含静态数据成员和静态函数成员。 通常,非 static 数据成员存在于类类型的每个对象中,但是 static 数据成员独立于该类的任意对象而存在,每个 static 数据成员是与类关联的对象,并不是与该类的对象关联。 静态成员函数没有 this 形参,可以直接访问所属类的 static 成员,但是不能直接使用非 static 成员。 使用静态成员的优点:( 1 )有利于类的封装,可以把 static 成员定义为私有成员,防止外部访问;( 2 ) static 成员是与特定的类关联的,在外部必须使用类名字做前缀,程序更加清晰;( 3 ) static 成员的名字是在类的作用域中,可以避免命名冲突。 (一)定义static成员 static 遵循正常的公有、私有访问限制。每一个要定义为 static 的成员前面都需要有 static ,这和访问限制不同。 static 成员函数可以直接定义在声明的后面,也可以在类的外面定义。当在类外面定义时,不需要 static 关键字。 在静态成员函数中,不可以使用 this 指针,因为静态成员函数是同一个类所有对象共有的。同样静态成员函数中也不可以使用非静态的数据成员,只可以使用类的静态数据成员。 class Student { public: static int getCount(); static int count; }; 和普通的数据成员不同, static 数据成员必须在类定义体的外部定义并初始化,定义的时候必须要有类名所前缀。 int Student::count=0; (二)使用static成员 可以使用作用域运算符“::”从类直间调用 static 成员,或者通过对象、引用该类类型对象的指针间接调用。如可以使用下面的方法访问静态成员。 Student::count=0; int n=Student::getCount(); 也可以通过类对象对静态成员进行访问: Student stu1; stu1.count=0; Student *s=syu1; int n=s-getCount(); 当在类的内部使用静态成员时,可以直接使用,不需要作用域运算符。此外可以使用非 static 成员的方法来使用 static 成员。 2.1 使用静态数据成员 #includeiostream using namespace std; class Test { public: static int n; Test(int x) { k = x; n++; } void disp() { cout "n= " n ", k=" k endl; } private: int k; }; int Test::n = 0; int main() { Test t1(10); t1.disp(); Test t2(20); t2.disp(); Test::n++; t2.disp(); system("pause"); return 0; } 2.2 使用静态成员函数 静态成员函数可以直接引用该类的静态数据成员和成员函数,但不能引用非静态成员。如果要引用非静态成员,必须通过参数传递的方式得到对象名,再通过对象名来引用。使用静态成员函数要注意的问题: 静态成员函数可以在类内定义,也可以在类外定义,在类外定义时不用再加关键字 static; 系统限定静态成员函数为内部连接,这样就不会因为与连接文件中的其他同名成员函数相冲突,保证了静态成员函数的安全性; 静态成员函数中没有隐含 this 指针; #includeiostream using namespace std; class Dot { static int t; int a, b; public: Dot(int x = 0, int y = 0) { a = x; b = y; t++; } Dot(Dot d); int geta() { return a; } int getb() { return b; } static void gett() { cout "object id:" t endl; } }; Dot::Dot(Dot d) { a = d.a; b = d.b; t++; } int Dot::t = 0; int main() { Dot::gett(); Dot d1(2, 3); cout "Dot d1:" d1.geta() "," d1.getb() endl; d1.gett(); Dot d2(d1); cout "Dot d2:" d2.geta() ", " d2.getb() endl; Dot::gett(); system("pause"); return 0; }