前言
static
关键字在C/C++/JAVA编程语言中都存在,而且在编程中经常会遇到,那么,在C/C++中,static
究竟意味着什么?那么static
修饰的变量和函数有什么样的特点呢?
本篇内容提要:
可以说,所有的静态变量都有几个共同特点:
- 在main函数执行之前就分配了内存(分配在全局数据区),整个程序执行完才会被销毁;
- 若没有初始化,会被程序自动初始化为
0
;
1.静态局部变量
一般的局部变量有一个问题,就是生命周期短,所以我们经常会定义全局变量,但是在实际的开发中,若全局变量定义太多,很容易出现重名的问题,而且也不容易区分,所以在一般的开发中,并不会定义过多的全局变量。
静态局部变量同时具备局部变量的防重复和生命周期长两个优点,可以很好地解决这个问题。
比方说:
#include <iostream> void print_fun() { static int a = 0; a++; printf("a = %d\t", a); } int main() { int add = 0; while (add < 10) { print_fun(); add++; } printf("\n"); }
打印输出:
从以上这个简单的例子,就可以说明问题。
2.静态全局变量
与局部静态变量类似,只不过静态全局变量虽然也是全部变量,但是仅限在本文件中使用。例如;
在mian.cpp
文件中程序如下:
#include <iostream> extern short ex; int main() { printf("%d\n", ex); }
而在example.c文件中,程序如下:
#include <iostream> static short ex = 0;
运行,出现如下问题:
可以看出,被static修饰的全局变量,仅仅作用在本文件中,其他文件中无法使用。
3.静态函数
静态函数相对来说比较简单,同样是对外不可见的。例如;
在mian.cpp
文件中编写程序如下:
#include <iostream> #include "example.h" int main() { static_print_ex(); }
在example.h
中编写程序如下:
#pragma once extern short ex; static void static_print_ex();
在example.cpp
中编写程序如下:
#include <iostream> #include "example.h" static void static_print_ex() { printf("The static external function is called!"); }
执行后,出现如下错误:
而在该函数的声明和定义中去掉static
后,再次执行,打印输出如下:
可以看到,程序可以正常执行,也就是静态函数的应用场景就是:
部分函数只想在本文件中使用,为了避免在其他文件中被使用,就可以采用这样的方法。
这个很好解释,就好比const
关键字一样,即使我们知道变量定义的时候知道是常量,不想再二次赋值,但是在后续的开发中,为了防止该变量的值被修改,还是会加上const
关键字。
4.静态成员变量
因为静态数据成员在全局数据区分配内存,由本类的所有对象共享,所以,它不属于特定的类对象,不占用对象的内存,而是在所有对象之外分配内存,在没有产生类对象时其作用域就可见。因此,在没有类的实例存在时,静态成员变量就已经存在,我们就可以操作它。例如:
假设有个用户类User
,m_Usersum
是当前系统中某产品的用户数量,所以在任何实例中,查询用户数量都是一样的,然而当某地的用户数量增加的时候,整个产品总的用户数量也会随之增加。
#include <iostream> class User { public: static int m_Usersum; static void SetUsersum(const int sum) { m_Usersum = sum; } static int GetUsersum() { return m_Usersum; } }; int User::m_Usersum = 100; int main() { User *User1; printf("There are %d users!\n", User1->GetUsersum()); User1->SetUsersum(101); User *User2; printf("There are %d users!\n", User2->GetUsersum()); User2->SetUsersum(102); printf("There are %d users!\n", User1->GetUsersum()); printf("There are %d users!\n", User2->GetUsersum()); }
打印输出:
可以看到,静态成员变量对每个类都是一样的,共享的,因为无论有多少个类,静态成员变量在内存中只有一份,所以无论在哪个实例中修改变量的值,在其他类中获取到的值都是一样的。
然后验证一下在类实例化之前访问静态成员变量。
编写代码如下:
#include <iostream> class User { public: static int m_Usersum; static void SetUsersum(const int sum) { m_Usersum = sum; } static int GetUsersum() { return m_Usersum; } }; int User::m_Usersum = 100; int main() { printf("There are %d users!\n", User::m_Usersum); }
打印输出:
可以看到,在类没有实例化的时候,静态成员变量已经初始化成功,我们可以随时访问。
5.静态成员函数
1.与普通函数相比,静态成员函数属于类本身,而不作用于对象,因此它不具有this
指针。
这句话如何理解呢?
静态成员函数确实属于类,但是和类的对象关系不大,不会牵扯到类的构造,析构当中来,所以也不会有this
指针。
关于this指针,网上有这样一段描述:
首先,我们都知道类的成员函数可以访问类的数据(限定符只是限定于类外的一些操作,类内的一切对于成员函数来说都是透明的),那么成员函数如何知道哪个对象的数据成员要被操作呢,原因在于每个对象都拥有一个指针:this
指针,通过this
指针来访问自己的地址。
2.静态成员函数不能访问非静态成员函数和非静态成员变量
这时候为什么呢?
还是和创建时间有关系,静态成员函数在类的实例化之前就已经存在了,这个时候类还没来得及实例化,根本无法访问非静态成员函数和非静态成员变量。
可以验证一下在类实例化之前访问静态成员函数。
#include <iostream> class User { public: static int m_Usersum; static void SetUsersum(const int sum) { m_Usersum = sum; } static int GetUsersum() { return m_Usersum; } }; int User::m_Usersum = 100; int main() { printf("There are %d users!\n", User::GetUsersum()); }
打印输出:
可以看到,程序可以正常运行。
参考文献
…
----------------------------------------------------------------------------------END----------------------------------------------------------------------------------