static的使用
静态变量基本认知
使用static定义的变量称为静态变量,可细分为静态全局变量、静态局部变量、静态函数。
静态全局变量和普通全局变量的区别
作用域不同:全局变量的作用域是整个工程,也就是在整个工程的不同文件夹中可以共享全局变量
静态全局变量的作用域是包含它的当前源文件
静态全局变量和普通全局变量都存放在全局数据区,如果没有初始化,系统会自动为其初始化为0;
静态局部变量和普通局部变量的区别
1、存储位置不同:静态局部变量存储在全局数据区,但其作用域还是局部的,静态局部变量不会因为某个子函数的完成而释放其内存空间,在其子函数外也不可调用它;
普通局部变量存放在堆栈中,若函数中定义一个局部变量,函数执行完之后,自动释放内存,若是使用new分配的局部指针变量,存放在堆中,需要手动进行释放,采用delete;
2、默认初值不同:若是没有初始化,静态局部变量的初始值为0,由于静态局部变量的生命周期是全局的,故对其的初始化只执行一次,后面遇到合法的初始化操作会自行跳过
若没有初始化,普通局部变量的初始值是随机的。
静态函数和普通函数的区别
主要区别还是作用域不同,静态函数的作用域是当前源文件,对该工程的其它源文件是隐藏的、不可见的。而普通函数的作用域在整个工程都是可以调用的。
静态数据成员的使用方法
静态数据成员是属于类的,而不是属于某个对象的,换句话说就是不管实例的对象有多少个,他们都共用一个静态数据成员,静态数据成员的初始化不能在类内部初始化,只能在类的外部初始化:
class A { private: int a; static int b; //定义静态数据成员 public: A(int a):a(a){} //数据成员初始化 }; int A::b=0; //静态常量数据成员初始化
对于静态数据成员可以将其定义为const,但静态函数不能定义为const,对于常量的静态数据成员只能在类外时初始化。
有些书籍上说在类内初始化,但经过反复验证似乎不行(感觉和类的数据成员不能在类声明时初始化矛盾,暂时还未理解???!!!,类内部的数据成员就是一个声明,不能对变量进行初始化),经过验证,发现只能在类外初始化,和静态变量类似。代码如下:
class A { private: const static int b; //声明 public: void show() { cout<<A::b<<endl; } }; const int A::b=22; //初始化
从上面的初始化过程可以看出,静态变量是属于类的,而不是某个对象,也可以说:不同的对象都用同一份静态变量成员。静态数据变量有以下两个特点:
1、即使没有对象,仍然可以访问静态数据成员
2、静态数据成员存储在全局数据区中,因此静态数据成员定义时需要分配空间,所以不能再类声明中初始化。
静态成员函数的使用
静态成员函数的使用与静态数据成员类似,静态成员函数也是属于类的,是类的一部分,不属于某个对象,是类的对象所共享的一个函数。普通成员函数都隐含的一个this指针,但静态成员函数是属于类的,故没有this指针这一说,没有this指针,静态函数也就无法访问普通的数据成员,只能访问静态数据成员。
参考程序如下:(设计了一个点的类:显示纵坐标和横坐标、显示实例了几个对象)
#include<iostream> using namespace std; class A { private: int x; int y; static int cnt; public: A(int x,int y):x(x),y(y) { cnt++; } void show() { cout<<"这个点的坐标是:"<<x<<","<<y<<endl; } static void show_cnt() { cout<<"绘制了第"<<cnt<<"个点"<<endl; //cout<<x<<y<<endl; //静态函数不能访问非静态变量 } }; int A::cnt=0; //静态数据成员初始化 int main() { int x = 0; int y = 0; while(1) { if(x>300 && y>400) { break; } A a(x,y); a.show(); a.show_cnt(); //静态函数属于类,任何对象都可以调用 x=(x+1)*2; y=(y+1)*2; } return 0; }
总结:静态成员函数可以被该类的所有对象访问
静态成员函数本身只能访问静态成员
静态对象和单例模型
静态对象
将对象定义为静态的,如上面的程序如果将对象定义为静态的,即:static A a(x,y);其运行结果则是只能实例一个对象。
利用静态成员实现单例模型
将类中数据成员除构造函数外都定义成static,构造函数的属性定义为private,这样就无法在类外实例对象,静态函数在类中只有一份,也就变相的实现了只能实例一个对象。
#include<iostream> using namespace std; class A { private: static int cnt; static A *s_list; A() {} //私有构造函数,只能在类中进行对象的实例 public: static A* new_list(); //定义一个public函数,通过调用该函数构建对象 void delete_list(); static void show() { cout<<"cnt="<<cnt<<endl; } }; int A::cnt=0; //静态数据成员初始化 A* A::s_list=NULL; A* A::new_list() { if(s_list==NULL) { s_list=new A; } cnt++; return s_list; } void A::delete_list() //用来删除对象,释放空间 { if(--cnt==0) { delete this; } } int main() { A* s1=A::new_list(); cout<<hex<<s1<<endl; A::show(); A* s2=A::new_list(); cout<<hex<<s1<<endl; A::show(); return 0; }
运行结果:
00352B48 cnt=1 00352B48 cnt=2