C/C++中静态成员变量和静态成员函数的含义与不同用法
C语言中static的语义
1.static变量:
1).静态局部变量
a.静态局部变量在函数内定义,生存期为整个源程序,但作用域与局部变量相同,只能在定义该变量的函数内使用。退出该函数后, 尽管该变量还继续存在,但不能使用它。
b.对基本类型的静态局部变量若在说明时未赋以初值,则系统自动赋予0值。而对自动变量不赋初值,则其值是不定的。
2).静态全局变量
全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。但是他们的作用域,非静态全局 变量的作用域是整个源程序(多个源文件可以共同使用); 而静态全局变量只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
2.static函数(也叫内部函数):
只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。
3. 在C语言中,由于没有类的概念,所以没有静态成员一说,在c中static的作用主要有2个:
一是隐藏功能,对于static修饰的函数和全局变量而言,其作用于局限于所在的文本,不能被其他文本内的函数使用
二是保持持久性功能,对于static修饰的局部变量而言,其存储区变更到静态存储区,程序结束不销毁
并且,因为存放在静态区,全局和局部的static修饰的变量,都默认初始化为0。
4.C中静态数据和静态函数的用法
C语言中定义一个静态变量和静态函数主要是为了满足某个文件的需求
比如我们在文件List.c中定义
static int count = 0; //静态变量
static int get_last_node(List *Head);//定义静态函数
二者的作用域都仅仅在文件List.c中。如果main函数在static int get_last_node(List *Head)
之前定义,那么就应该在头文件后面用语句:
static int get_last_node(List *Head);//定义静态函数进行声明。
如果main定义在static int get_last_node(List *Head)之后则不需要。(建议静态函数都在头文件后声明)
#include<stadio.h>
static int count = 0; //静态变量
static int get_last_node(List *Head);//定义静态函数
void main()
{
List *Head;
.....
int ret = get_last_node(Head);
......
}
static int get_last_node(List *Head)
{
.....
return ret;
}
-----------------------------------------------------------
#include<stadio.h>
static int count = 0; //静态变量
static int get_last_node(List *Head)
{
.....
return ret;
}
void main()
{
List *Head;
.....
int ret = get_last_node(Head);
......
}
------------------------------------------------------------
C++语言中static的语义
在c++中,由于面向对象的思维,它与C语言中的作用有一些不同,有了类中静态成员的说法。静态成员不属于对象,而属于类。不创建对象也可调用。从代码形式上来说没有任何区别。普通类成员函数与静态成员函数的区别在于普通成员函数有一个隐藏的调用参数(this)指针。所以就是说静态成员函数没有对象也可调用。
一、静态成员变量
类的静态成员变量是直接与类联系,属于类的成员而不是对象,供所有对象共享,存放于全局区,因而不计入类的内存计算。静态成员变量可以通过类直接访问。
(1)静态成员变量的初始化
静态成员不属于类的任何对象,所以并不是对象建立时被定义的,所以它不能由类的构造函数初始化(否则每定义一个对象就要初始化一次),一般也不能在类内初始化。
关键字static只出现类的内部。
1、在类外定义且初始化
2、常量静态成员可以在类内初始化
一般来说无论怎样静态成员变量都需要在类外进行定义(定义可以初始化赋值,如果不显示初始化就是默认初始化)
(2))静态成员变量的访问
1、使用类作用域运算符直接访问
2、使用类的对象访问
3、成员函数可以直接访问
范例:
#include <iostream> using namespace std; class A { public: A(){} int val(); static int stval(); static int ac; const static int bc=2;//常量静态成员可以在类内初始化 private: static int dc; int nn; }; int A::ac=1; //类外定义且初始化,//类的静态成员变量需要在类外分配内存空间 int A::dc=1; int A::stval() { // nn=10; 静态成员函数不能调用非静态成员 dc=20; return dc; } int A::val() { dc=ac; //成员函数直接访问 return dc; } int main() { A a; cout<<a.ac; //使用类的对象访问 cout<<a.val(); cout<<A::bc; //类作用域运算符直接访问 cout<<A::stval(); cout<<a.stval(); return 0; }
(3)静态成员能使用的某些场景,普通成员不可以的
1、静态成员可以是不完全类型
2、静态成员可以作为默认实参
3、作为类对象的共享成员
二、静态成员函数
1、静态成员函数类似于静态成员变量都属于类而不是对象。
2、静态成员函数仅可以调用类的静态成员变量,不可以调用普通成员变量。
3、不具有this指针,因而自然不能声明为const。
4、如果类的成员函数想作为回调函数来使用,一般情况下只能将它定义为静态成员才行。
class A { public: A(){} int val(); // static int stval ()const; 出错,不具有this指针 private: static int bc=2;//常量静态成员可以在类内初始化 };
静态成员函数在C++中的作用很强大,包括后边的介绍的单例模式、二阶构造模式,都用到静态成员函数及静态成员变量。
下边的图为静态成员函数与普通成员函数的比较
关于静态局部变量参看:https://www.cnblogs.com/liushui-sky/p/5757365.html
在局部变量前加上“static”关键字,就成了静态局部变量。静态局部变量存放在内存的全局数据区。函数结束时,静态局部变量不会消失,每次该函数调用时,也不会为其重新分配空间。它始终驻留在全局数据区,直到程序运行结束。静态局部变量的初始化与全局变量类似.如果不为其显式初始化,则C++自动为其初始化为0。
静态局部变量与全局变量共享全局数据区,但静态局部变量只在定义它的函数中可见。静态局部变量与局部变量在存储位置上不同,使得其存在的时限也不同,导致对这两者操作 的运行结果也不同。
对静态局部变量的说明:
(1) 静态局部变量在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,存储在动态存储区空间(而不是静态存储区空间),函数调用结束后即释放。
(2) 为静态局部变量赋初值是在编译时进行的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。而为自动变量赋初值,不是在编译时进行的,而是在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
(3) 如果在定义局部变量时不赋初值的话,对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符型变量)。而对自动变量来说,如果不赋初值,则它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配的单元中的值是不确定的。
(4) 虽然静态局部变量在函数调用结束后仍然存在,但其他函数是不能引用它的,也就是说,在其他函数中它是“不可见”的。
参考:
https://www.cnblogs.com/yulei0713/p/11327169.html
https://www.cnblogs.com/kiplove/p/6875371.html
https://blog.csdn.net/lms1008611/article/details/81408236