1.(面向过程)静态局部变量

        在局部变量前,加上关键字static,该变量就被定义成为一个静态局部变量。
        静态局部变量的特点:
        1)位于全局数据区,一般的局部变量位于栈区;
        2)静态局部变量在程序执行到该对象的声明处时被首次初始化,即以后的函数调用不再进行初始化;
        3)静态局部变量一般在声明处初始化,如果没有显式初始化,会被程序自动初始化为0。一般的局部变量貌似是随机值;
        4)静态局部变量始终驻留在全局数据区,直到程序运行结束。但其作用域为局部作用域,当定义它的函数或语句块结束时,其作用域随之结束;

2.(面向过程)静态全局变量

        在全局变量前,加上关键字static,该变量就被定义成为一个静态全局变量。
        静态的全局变量主要作用是将变量的连接性变为内部链接,别的文件不可以访问。

3.(面向过程)静态函数

        函数原型与定义同时加上关键字static,该变量就被定义成为一个静态函数。静态函数的static的作用类似静态全局变量。

4.(面向对象)静态成员变量

        在类内成员变量的声明前加上关键字static,该数据成员就是类内的静态数据成员。
        静态成员变量的特点:
        1)静态成员变量是该类的所有对象所共有的。对于普通成员变量,每个类对象都有自己的一份拷贝。而静态成员变量一共就一份,无论这个类的对象被定义了多少个,静态成员变量只分配一次内存,由该类的所有对象共享访问。所以,静态数据成员的值对每个对象都是一样的,它的值可以更新;
        2)因为静态数据成员在全局数据区分配内存,由本类的所有对象共享,所以,它不属于特定的类对象,不占用对象的内存,而是在所有对象之外开辟内存,在没有产生类对象时其作用域就可见。因此,在没有类的实例存在时,静态成员变量就已经存在,我们就可以操作它;
        3)静态成员变量存储在全局数据区。static 成员变量的内存空间既不是在声明类时分配,也不是在创建对象时分配,而是在初始化时分配。静态成员变量必须初始化,而且只能在类体外进行。否则,编译能通过,链接不能通过。初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化,一般是 0。静态数据区的变量都有默认的初始值,而动态数据区(堆区、栈区)的变量默认是垃圾值。
        4)static 成员变量和普通 static 变量一样,编译时在静态数据区分配内存,到程序结束时才释放。这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
        5)静态数据成员初始化与一般数据成员初始化不同。初始化时一定不加 static,但必须要有数据类型。被 private、protected、public 修饰的 static 成员变量都可以用这种方式初始化。静态数据成员初始化的格式为:<数据类型><类名>::<静态数据成员名>=<值>
        6)类的静态成员变量访问形式1:<类对象名>.<静态数据成员名> 2:<类类型名>::<静态数据成员名> 。在类的内部与其他的变量一样正常使用;
        7)静态数据成员和普通数据成员一样遵从public,protected,private访问规则;
        8)sizeof 运算符不会计算 静态成员变量;

       设置静态成员(变量和函数)这种机制的目的是将某些和类紧密相关的全局变量和函数写到类里面,看上去像一个整体,易于理解和维护。如果想在同类的多个对象之间实现数据共享,又不要用全局变量,那么就可以使用静态成员变量。也即,静态数据成员主要用在各个对象都有相同的某项属性的时候。比如对于一个存款类,每个实例的利息都是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处:

        1)不管定义多少个存款类对象,利息数据成员都共享分配在全局数据区的内存,节省存储空间。
        2)一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了。

同全局变量相比,使用静态数据成员有两个优势:

       1) 静态成员变量没有进入程序的全局命名空间,因此不存在与程序中其它全局命名冲突的可能。
        2)可以实现信息隐藏。静态成员变量可以是private成员,而全局变量不能。

5.(面向对象)静态成员函数

        与静态成员变量类似,我们也可以声明一个静态成员函数。静态成员函数可以在类内定义也可以在类外定义。
        静态成员函数为类服务而不是为某一个类的具体对象服务。静态成员函数与静态成员变量一样,都是类的内部实现,属于类定义的一部分。普通成员函数必须具体作用于某个对象,而静态成员函数并不具体作用于某个对象。
        普通的成员函数一般都隐含了一个this指针,this指针指向类的对象本身,因为普通成员函数总是具体地属于类的某个具体对象的。当函数被调用时,系统会把当前对象的起始地址赋给 this 指针。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。
        与普通函数相比,静态成员函数属于类本身,而不作用于对象,因此它不具有this指针。正因为它没有指向某一个对象,所以它无法访问属于类对象的非静态成员变量和非静态成员函数,它只能调用其余的静态成员函数和静态成员变量。从另一个角度来看,由于静态成员函数和静态成员变量在类实例化之前就已经存在可以访问,而此时非静态成员还是不存在的,因此静态成员不能访问非静态成员。
        静态成员函数的特点
        1)出现在类体外的函数定义不能指定关键字static;
        2)静态成员之间可以相互访问,即静态成员函数(仅)可以访问静态成员变量、静态成员函数;
        3)静态成员函数不能访问非静态成员函数和非静态成员变量;
        4)非静态成员函数可以任意地访问静态成员函数和静态数据成员;
        5)由于没有this指针的额外开销,静态成员函数与类的函数相比速度上会稍快;
        6)静态成员函数不能是虚函数。静态成员函数理论是可继承的。但是静态成员函数是编译时确定的,无法动态绑定,不支持多态,因此不能被重写,也就不能被声明为虚函数;
        7)不可以同时用const和static修饰成员函数。C++编译器在实现const的成员函数的时候为了确保该函数不能修改类的实例的状态,会在函数中添加一个隐式的参数const this*。但当一个成员为static的时候,该函数是没有this指针的。也就是说此时const的用法和static是冲突的。我们也可以这样理解:两者的语意是矛盾的。static的作用是表示该函数只作用在类型的静态变量上,与类的实例没有关系;而const的作用是确保函数不能修改类的实例的状态,与类型的静态变量没有关系。因此不能同时用它们;
        8)调用静态成员函数两种方式:通过成员访问操作符(.)和(->),也即通过类对象或指向类对象的指针调用静态成员函数;直接通过类来调用静态成员函数。<类名>::<静态成员函数名>(<参数表>)。也即,静态成员不需要通过对象就能访问;

参考链接: