static静态不是很静
在类中定义变量时,不会开辟存储空间,只有类定义一个对象时才会开辟类中成员变量的内存空间,且建立一个对象开辟一次,大小与类中的成员变量及函数有关。而static在静态区开辟内存空间,不占用内存空间。
1.函数内部的静态变量
在程序运行时,我们有时候希望一个变量的值在函数两次调用时他能分别保持上一次运行的结果,而不是每次调用都初始化为初值,实现这样的效果可以通过定义一个全局变量来实现,但是这个全局变量不仅这个函数可以使用,别的函数同样也可以改变它的值,不能完全保证只受一个函数控制,但是,如果在函数内部定义一个static变量,这个变量存储在静态数据区,而不是堆栈中,这个变量只在函数第一次调用时初始化一次,以后它将在两次函数调用之间保持它的值。
2.函数内部的静态对象
在类中,用户自定义类型,必须用构造函数初始化。因此,如果在定义一个静态对象是时没有指定构造函数参数,这个类必须有默认的构造函数。
1 class X{ 2 int i; 3 public: 4 X(int ii = 0) : i(ii) { }//默认构造函数 5 ~X(); 6 }; 7 8 void f() 9 { 10 static X x1(47);//有参构造i=47; 11 static X x2;//调用默认的构造函数i=0; 12 } 13 14 int main() 15 { 16 f(); 17 //程序调用f()时,只有第一次调用才需要执行构造函数,即只初始化一次。 18 }
3.控制连接
有时候想让一个变量在文件范围内是可见的,这个文件内的所有函数都可以使用它,但不想让这个文件之外的函数看到或访问该变量,不与外部标识符冲突。就可以使用sataic在.cpp中来限制变量,这样,这个变量只局部与该单元,在其它翻译单元中可以使用同样的名字而不会冲突。
4.定义静态数据成员
在类的数据成员中如果是静态常量(static const)可以在类内提供定义赋值初始化,但是对于全部类型的数组(即使是静态常量数组)必须为其提供专门的外部定义。
1 class WithStatic 2 { 3 static int x;//在类中声明,实现中定义(是静态,但非常量),类的静态数据成员有单独的存储空间,不管产生了多少个对象。 4 static int y; 5 static const int scsize[ ];// 静态数组必须在类的内部声明,实现中定义赋值初始化, 6 static int sxsize[ ];//不能在声明时定义初始化。; 7 static const int z=100;// 静态常量可以在类中声明时定义初始化, 8 static const int w; //也可以类中声明,实现中定义初始化。 9 Public: 10 void print() const 11 { 12 cout << x << endl; 13 cout << y << endl; 14 15 } 16 17 }; 18 19 int WithStatic::x = 1; 20 //定义必须出现在类的外部,且只能定义一次,最终使用由类的构造者控制 21 int WithStatic::y = 2; 22 const int WithStatic::scsize[ ] = { 99,78,32,12}; 23 //数组的定义也只能在类的外部实现。 24 int WithStatic::sxsize[ ] = { 99,78,32,12}; 25 const int WithStatic::w=10;//常量也可以在类的外部实现。 26 27 int main() 28 { 29 WithStatic ws; 30 ws.print(); 31 32 }
5.静态成员函数
像静态数据成员一样,静态成员函数为类的全体对象服务,而不是某个特殊对象的专属,这样就不需要定义一个全局函数,而是移到了类的内部起到到全局的作用。静态成员函数一般用类域(类名::函数名())去调用,从概念上体现静态成员函数为整个类所有。
1 class X 2 { 3 Public: 4 static void f(); 5 }; 6 7 int main() 8 { 9 X::f(); 10 //静态成员函数可以自我调用,加上作用域限制符即可。它同样也可以由类的对象.或->去调用,但是普通成员函数只能通过对象调用。 11 }
静态成员函数不能访问一般的数据成员(没有默认的this指针),只能访问静态数据成员,也只能调用其他的静态成员函数。
1 class X 2 { 3 int i; 4 static int j; 5 public: 6 7 X(int ii = 0) : i(ii) 8 { 9 j=i; 10 } 11 12 int val() const { return i;} 13 14 static int incr() 15 { 16 i++;//非法访问,i不是静态变量。 17 j++;//正确 18 return j; 19 } 20 21 static int f() 22 { 23 val();//非法,val()不是静态函数。 24 return incr(). 25 } 26 27 }; 28 29 int X::j = 5;//定义初始化 30 31 int main() 32 { 33 X x; 34 X* ip = &x; 35 x.f(); 36 ip->f(); 37 X::f(); 38 }