面向对象设计中的static
1.静态成员变量
(1)静态成员变量是属于整个类的全局变量,可以被所有对象共享,它不属于某个对象;普通成员变量是属于对象的变量,不能被所有对象共享。
#include<iostream> using namespace std; class A { public: static int x; }; int A::x = 10; //初始化静态成员变量x int main() { A a, b, c; cout<<a.x<<endl<<b.x<<endl<<c.x; return 0; }
在该类中3个对象a,b,c共享静态成员变量x。
(2)使用静态成员变量时,可以不将其限定为某个具体对象,只与类名连用即可。
如: A::x ; 而不用: A a; a.x;
(3)静态成员变量在没有对象前就存在:
#include<iostream> using namespace std; class A { public: static int n; }; int A::n = 0; //初始化静态成员变量n int main() { int i; for(i=0; i<5; i++) { A::n++; cout<<A::n<<" "; } return 0; }
输出:1 2 3 4 5
上例没有创建对象,通过类名和限定符访问静态成员变量n,并对其进行自加,说明静态成员变量在没有对象之前就存在。
(4)私有静态成员变量:假如我们不想让类外的所有函数都可以访问它,则可以将它声明为私有,这样只有通过该类的公有成员函数才能访问它,但前提是必须创建该类的一个对象。
#include<iostream> using namespace std; class A { public: void func() {cout<<A::x;} //用该函数访问私有静态成员变量x private: static int x; }; int A::x = 1000; //初始化静态成员变量x int main() { A a; a.func(); return 0; }
同全局变量相比,使用静态数据成员有两个优势:
1.静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其它全局名字冲突的可能性;
2.可以实现信息隐藏;静态数据成员可以是private成员,而全局变量不能。
2.静态成员函数
(1) 静态成员函数与静态成员变量是一样的,它们不属于一个对象,而是属于整个类。
#include<iostream> using namespace std; class A { public: void static show() {cout<<A::n; n++;} //静态成员函数show(),输出私有静态成员变量n并将n自加 private: static int n; }; int A::n = 0; int main() { int i; for(i=0; i<5; i++) { A::show(); } return 0; }
输出:01234
从上例可知,共有的静态成员函数show()在未创建对象时也可以使用,它的调用与静态成员变量一样;
也可以通过对象里访问静态成员函数:
如: A a, b; a.show(); b.show();
(2) 普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数。
#include<iostream> using namespace std; class A { public: void show(int i) {x = i; cout<<x;} //void static show1(int j) {x = j; cout <<x;} //静态成员函数没有指向对象的this指针,所以不能访问对象的成员变量x private: int x; }; int main() { A a; a.show(1); //a.show1(1); return 0; }
第7行定义了一个静态成员函数show1(),并在该函数体内试图用this指针来访问对象的成员变量x,这么做会报错,所以注释了起来。
注意:
1.静态成员之间可以相互访问,包括静态成员函数访问静态成员变量和访问静态成员函数;
2.非静态成员函数可以任意地访问静态成员函数和静态成员变量;
3.静态成员函数不能访问非静态成员函数和非静态成员变量;
4.由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;
5.不能将静态成员函数定义为虚函数;
6.静态成员初始化与一般数据成员初始化不同: 初始化在类体外进行,而前面不加static,以免与一般静态变量或对象相混淆;初始化时使用作用域运算符来标明它所属类;