作者:常德锦江-余欢 | 来源:互联网 | 2023-10-11 17:00
在C++代码中static 关键字随处可见,到底有什么用呢?下面结合类class举几个简单的例子。
文章目录
- 类中静态成员变量与静态成员函数的特点
- 静态成员变量示例代码
- 静态成员函数示例代码
- 访问权限
类中静态成员变量与静态成员函数的特点
在类中以static 修饰的变量以及函数称为静态成员变量和静态成员函数,特点下:
静态成员变量:
- 在编译阶段分配内存,存储于全局区。
- 所有对象共享一份数据,因此不属于特定哪个某个对象。(非静态成员变量隶属于特定的对象)
- 类内声明,类外初始化。
静态成员函数:
- 所有对象共享同一个函数,因此不属于特定哪个某个对象。
- 静态成员函数只能访问静态成员变量。
静态成员变量示例代码
上菜!!!
让我们定义一个Sta 的类(class),它有两个静态成员变量,_a和_count还有一个非静态成员函数display用于打印数据。
#include
#include
#include
using namespace std;class Sta
{
public:Sta() { _count++; }void display() { cout << typeid(*this).name() << _count << " &#39;s " << "static member _a is " << _a << endl; }static int _a; static int _count;
};int Sta::_a = 0;
int Sta::_count = 0;int main()
{Sta sta1; sta1.display(); Sta sta2; sta2.display(); sta2._a = 520; cout << "sta1&#39;s static member _a: " << sta1._a << endl; cout << "***************************************" << endl;cout << Sta::_a; return 0;
}
先不管_count,我们看看_a的变化。静态成员变量_a在类外初始化为0,主函数先后创建两个类,创建的同时display( )打印出来的_a均为0,然后通过sta2访问并将_a的值修改为520,再通过sta1获取_a的值并打印输出。
如果_a是一般的成员变量,即非静态成员变量的话,sta2修改它的值是不会改变sta1中_a的值。因为每个对象都有自己的成员变量,它们并不共享切毫无关联!但一开始sta1.display()出来的_a是0,通过sta2将_a修改成520之后,再打印出来的sta1._a值也变为了520,可见这两份数据有关联,准确地说这两份数据是同一份,即对象sta1、sta2共享同一份_a数据。
既然静态成员不隶属于任何一个对象,那么我们能否不像非静态成员变量那样通过对象来访问呢?(sta1._a)答案是肯定的!
下面这行就是直接通过类名访问静态成员变量,不需要创造任何对象!但要说清楚该变量是哪个作用域下的(Sta::)。
cout <
静态成员变量就像一辆共享单车,10个能扫码开锁的人好比是10个对象,这辆车不属于任何一个人(对象),但是每个人都能改变这辆车的状态,骑、在哪骑,停、停在哪…
同样作为静态成员变量的_count也不属于任何一个对象,无论哪个对象对其作出修改,这份独一无二的数据就会改变。我通过构造函数对它进行自增运算,Sta每构造一个新的对象count就会+1,一直累加下去。
typeid运算符
其中typeid运算符会返回一个type_info对象,该对象的name( )函数会返回const char*,用以表示类名。typeid运算符接收一个对象作为参数,使用该运算符前记得包含头文件。通过得到的类名后面追加累加的_count就可以打印不同对象的名称了。(严格来说并不是对象的名称,我这里只是用来做实验说明这个效果,哈哈~~~)
静态成员函数示例代码
静态成员函数特点与静态成员变量类似,所有对象共享一份,不属于任何一个对象!同样也可以不用创建对象,通过类名访问。
上面介绍特点的时候说过,静态成员函数只能访问静态成员变量,因此它不能访问非静态成员变量了,这又是为什么呢?
先看看这段代码,有没有问题?
class Sta
{
public:int _b;private:static int s_a; static int sta_display() { return _b; }};int Sta::s_a = 0; int main()
{return 0;
}
答案还是肯定的!编译器会提示这么一个错误。
意思就是非静态成员变量必须通过对象来访问。因为静态成员函数不属于任何对象,因此它提供不了一个特定的对象来访问_b,所以报错了。
但常识告诉我们sta_display( )作为Sta类中的成员函数理应可以访问成员变量_b。我们看看常识告诉我们的操作是怎么实现的。我们再来一个非静态成员函数display( )就可以正常访问_b了。(注意看sta_display( )那行_b下面是有红色波浪线,说明有错误)
事实上,非静态成员函数也只有一份,那它怎么提供特定对象呢?当非静态成员函数display( )访问_b时,其实编译器会自动提供this指针,即转化成这样
int display() { return this->_b; }
this指针
静态成员函数无需通过对象调用(类名即可),但非静态成员函数必须通过特定对象来调用,当实例化出来的对象调用该函数时,this指针会指向该对象,即this指针指向被调用的成员函数所属的对象!。自然也可以为非静态成员变量_b提供特定对象了(this指针嘛)。而静态成员函数没有this指针,编译器也不知道你要访问哪个_b,当然会出错了!
有人会问静态成员函数不会自动提供this指针吗?答案终于是否定了。我们假设它会自动提供this指针的话…那么静态成员函数如果用类名(作用域)这种方式访问的话,没有创建任何对象哦,那请问this指针指向谁?逻辑上行不通了。
所以静态成员函数只能老老实实访问静态成员变量,反正静态成员变量不属于任何对象,正好静态成员函数也不能提供任何对象!上面代码注释行是行得通的!
访问权限
补充一点:若像上面那个Sta类那样将静态成员变量、函数声明为private(私有作用域)的话,类外是不可访问的。虽然它们是共享的,但也有访问权限。既开放(类内),又关闭(类外)!真银杏~~~