static静态成员变量、成员函数的作用

  数据成员可以分为静态变量、非静态变量两种。
  静态成员:静态类中的成员加入static修饰符,即是静态成员,可以使用类名+静态成员名访问此静态成员,因为静态成员存在于内存,非静态成员需要实例化才会分配内存,所以 静态成员不能访问非静态成员,因为静态成员存在于内存,所以非静态成员可以直接访问类中的静态成员。
  非静态成员:所有没有加static的成员都是非静态成员,当类被实例化后,可以通过实例化的类名进行访问,非静态成员的生存期决定于该类的生存期,而静态成员则不存在生存期的概念,因为静态成员始终驻留在内存中。
  一个类中可以包含静态成员和非静态成员,类中也包括静态构造函数和非静态构造函数。
以下分两方面来说,第一方面主要是相对于面向过程而言,在这方面不涉及类;另一方面相对于面向对象来说,主要说明static在类中的作用。
一、在面向过程设计中的static关键字
1、静态全局变量
定义:在全局变量前加上关键字static,该变量就被定义成一个静态全局变量。
特点:
   A 、该变量在全局数据区分配内存
   B、初始化:如果不显式初始化,那么将被饮食初始化为0(自动变量是随机的,除非是显式初始化)
   C、该变量只在本源文件可见,严格地讲,应该从定义之处开始到本文件结束。

1.  #include <iostream>  

3.  using namespace std;  

5.  void fun();  

7.  static int n;  

9.  void main()  
10.  {  
11.  n = 20;  
12.  cout<<n<<endl;  
13.  fun();  

15.  }  

17.  void fun()  
18.  {  
19.  n++;  
20.  cout<<n<<endl;  
21.  }

                      输出 20 21

  D、文件作用域下声明的const的常量默认为static存储类型。
    静态变量都在全局数据区分配内存,包括静态局部变量。对于一个完整的程序,在内存中的分布情况如下:
    代码区
    全局数据区
    堆区
    栈区
  一般在程序中,由new产生的动态数据区放在堆区中,函数内部的自动变量存放在栈区。自动变量一般会随着函数的退出而释放空间,静态数据(即使是函数内部的静态局部变量)也存放在全局数据区中。全局数据区的数据并不会因为函数的退出而释放空间。
  如果把上例中的
    static int n;修改为
    nt n;//全局变量。它可以实现变量在文件中的共享
  但是静态全局变量有以下好处:
    在其他文件中可以定义相同名字的变量,而不会发生冲突。

#include <iostream>    
using namespace std;    
void fun();    
static int n;    
void main()  
{  
    n = 20;  
    cout<<n<<endl;  
    fun();  
      
}  

    
FILE 2  
#include <iostream>    
using namespace std;    
extern int n;    
void fun()  
{  
    n++;  
    cout<<n<<endl;  
} 

2、静态局部变量

定义:在局部变量前加上static关键字时,就定义了静态局部变量。


1.  FILE 3   
2.  #include <iostream>  

4.  using namespace std;  

6.  void fun();  

8.  void main()  
9.  {  
10.  fun();  
11.  fun();  
12.  fun();  

14.  }  

16.  void fun()  
17.  {  
18.  static int n = 10;  
19.  n++;  
20.  cout<<n<<endl;  
21.  }  

  通常,在函数体内定义了一个变量,每当程序运行到该语句时都会给该局部变量分配栈内存,但随着程序退出函数体,系统就会收回栈内存,局部变量也相应失效。但是有时候我们需要在两次调用之间对变量的值进行保存,通常的想法是定义一个全局变量来实现,但是这样一来,变量已经不再属于函数本身了,不再仅受函数的控制,给程序的维护带来不便。

  静态局部变量正好可以解决这个问题。静态局部变量保存在全局数据区,而不是保存在栈中,每次的值保持到下一次调用,直到下次赋新值。

特点:

A、该变量在全局数据区分配内存
B、初始化:如果不是显式初始化,那么将被隐式初始化为0,以后的函数调用不再进行初始化。
C、它始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域。当定义它的函数或语句块结束时,其作用域也随之结束。

3、静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其他文件使用。

1.  FILE 4   
2.  #include <iostream>  

4.  using namespace std;  

6.  static void fun();  

8.  void main()  
9.  {  
10.  fun();  

12.  }  

14.  void fun()  
15.  {  
16.  int n = 10;  
17.  n++;  
18.  cout<<n<<endl;  
19.  }  

定义静态函数的好处:静态函数不能被其他文件使用。在其他文件中可以定义相同名字的函数,不会发生冲突。

二、面向对象的static关键字

1、静态数据成员

在类内数据成员的声明前加上关键字static,该数据成员就是类内的静态数据成员。

[cpp] [view plain](http://blog.csdn.net/kerry0071/article/details/25741425/#) [copy](http://blog.csdn.net/kerry0071/article/details/25741425/#)

1.  #include <iostream>  

3.  using namespace std;  

5.  class MyClass  
6.  {  
7.  public:  
8.  MyClass(int a, int b, int c);  
9.  void fun();  
10.  private:  
11.  int a,b,c;  
12.  static int sum;//声明静态数据成员  
13.  };  

15.  int MyClass::sum = 0;  
16.  MyClass::MyClass(int a, int b, int c)  
17.  {  
18.  this->a = a;  
19.  this->b = b;  
20.  this->c = c;  
21.  sum += a+b+c;  
22.  }  

24.  void MyClass::fun()  
25.  {  
26.  cout<<"sum = "<<sum<<endl;  
27.  }  
28.  void main()  
29.  {  
30.  MyClass M(1,2,3);  
31.  M.fun();  

33.  MyClass N(4,5,6);  
34.  N.fun();  
35.  }  

  从以上的程序可以看出,静态数据成员有以下特点:
  对于非静态数据成员,每个类对象都有自己的拷贝。而静态数据成员被当作是类的成员。无论这个类的对象定义了多少个,静态数据成员在程序中也只有一份拷贝,由该类型的所有对象共享访问。即静态数据成员是该类的所有对象所共有的。对该类的多个对象来说,静态数据成员只分配一次内存,供所有对象共用。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新。
  静态数据成员存储在全局数据区,静态数据成员定义时要分配空间,所以不能在类声明中定义。应该在类外定义。
  静态数据成员和普通数据成员一样遵从public、private、protected访问规则。
  由于静态数据成员在全局数据区分配内存,属于本类的所有对象共享,它不属于特定的类对象,在没有产生类对象时作用域就可见。即在没有产生类的实例时,我们就可以操作它。静态数据成员的初始化与一般数据成员的初始化不同,即它的初始化格式为:

    <数据类型><类名>::<静态数据成员> = <值>

  类的静态数据成员有两种访问方式:
  如果静态数据成员的访问权限允许的话,即为public成员,可在程序中,按上述格式来引用静态数据成员;
  静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对一个存款类,每个实例的利息都是相同的,所以把利息可以设为存款类的静态数据成员。这有两个好处,一是不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,所以节省了存储空间。二是一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了。
  同全局变量相比,使用静态数据成员有两个优势:
(1)静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性;
(2)可以实现信息隐藏。静态数据成员可以使private成员,而全局变量不能。

4、静态成员函数

  与静态数据成员一样,我们也可以创建一个静态成员函数,它为类的全部服务,而不是为某一个类的具体对象服务。静态成员函数与静态数据成员一样,都是在类的内部实现,属于类定义的一部分。普通的成员函数一般都隐藏了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this指针是缺省的、但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针,从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

1.  #include <iostream>  

3.  using namespace std;  

5.  class MyClass  
6.  {  
7.  public:  
8.  MyClass(int a, int b, int c);  
9.  static void fun();  
10.  private:  
11.  int a,b,c;  
12.  static int sum;//声明静态数据成员  
13.  };  

15.  int MyClass::sum = 0;  
16.  MyClass::MyClass(int a, int b, int c)  
17.  {  
18.  this->a = a;  
19.  this->b = b;  
20.  this->c = c;  
21.  sum += a+b+c;  
22.  }  

24.  void MyClass::fun()  
25.  {  
26.  cout<<"sum = "<<sum<<endl;  
27.  }  
28.  void main()  
29.  {  
30.  MyClass M(1,2,3);  
31.  M.fun();  

33.  MyClass N(4,5,6);  
34.  N.fun();  
35.  MyClass::fun();//静态成员函数的访问  
36.  }  

关于静态成员函数,可以总结以下几点:

(1)出现在类体外的函数不能指定关键字static;(类的成员函数,在类外定义,不需要(也不能)加static关键字)

(2)静态成员之间可以互相访问,包括静态成员函数访问静态数据成员和访问静态成员函数;

(3)非静态成员函数可以任意地访问静态成员函数和静态数据成员;

(4)静态成员函数不能访问非静态成员函数和非静态数据成员;

(5)由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比,速度上会有少许的增长;

(6)调用静态成员函数,可以用成员访问操作符(.)和(->)为一个类的对象或指向类对象的指调用静态成员函数。

静态函数主要为了调用方便,不需要生成对象就能调用

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,085评论 1 32
  • 整理来自互联网 1,JDK:Java Development Kit,java的开发和运行环境,java的开发工具...
    Ncompass阅读 1,534评论 0 6
  • 一:java概述: 1,JDK:Java Development Kit,java的开发和运行环境,java的开发...
    慕容小伟阅读 1,766评论 0 10
  • C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static。前者应用于普通...
    yangqi916阅读 381评论 0 0
  • 0415子怡播报 各位叔叔阿姨老师们大家好,是今天的播报员陈子怡,我今天播报的主题是——让自己成为自信的人 2...
    简_丹生活阅读 407评论 0 2