C++随笔 静态成员变量与静态成员函数的使用 超详细!!!

在C++代码中static 关键字随处可见,到底有什么用呢?下面结合class举几个简单的例子。

类中静态成员变量与静态成员函数的特点

在类中以static 修饰的变量以及函数称为静态成员变量和静态成员函数,特点下:

静态成员变量:

  1. 在编译阶段分配内存,存储于全局区。
  2. 所有对象共享一份数据,因此不属于特定哪个某个对象。(非静态成员变量隶属于特定的对象)
  3. 类内声明,类外初始化。

静态成员函数:

  1. 所有对象共享同一个函数,因此不属于特定哪个某个对象。
  2. 静态成员函数只能访问静态成员变量。

静态成员变量示例代码

上菜!!!
让我们定义一个Sta 的类(class),它有两个静态成员变量,_a和_count还有一个非静态成员函数display用于打印数据。

#include <iostream>
#include <string>
#include <typeinfo>
using namespace std;

class Sta 
{
public:
	Sta() { _count++; }
	void display() { cout << typeid(*this).name() << _count << " 's " << "static member _a is " << _a << endl; }
	static int _a; //类内声明
	static int _count;
};

int Sta::_a = 0; //类外初始化,初始化不加static关键字,否则编译不通过
int Sta::_count = 0;

int main()
{
	Sta sta1; //实例化对象
	sta1.display(); //调用打印display打印输出_a
	Sta sta2; //同上
	sta2.display(); //同上
	sta2._a = 520;  //通过对象sta2访问并修改_a!!!
	cout << "sta1's static member _a: " << sta1._a << endl; //通过sta1获取_a的值,再次打印观察结果
    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 << Sta::_a; //用类名访问静态成员变量,同样可以输出520

静态成员变量就像一辆共享单车,10个能扫码开锁的人好比是10个对象,这辆车不属于任何一个人(对象),但是每个人都能改变这辆车的状态,骑、在哪骑,停、停在哪…

同样作为静态成员变量的_count也不属于任何一个对象,无论哪个对象对其作出修改,这份独一无二的数据就会改变。我通过构造函数对它进行自增运算,Sta每构造一个新的对象count就会+1,一直累加下去。

typeid运算符

其中typeid运算符会返回一个type_info对象,该对象的name( )函数会返回const char*,用以表示类名。typeid运算符接收一个对象作为参数,使用该运算符前记得包含头文件<typeinfo>。通过得到的类名后面追加累加的_count就可以打印不同对象的名称了。(严格来说并不是对象的名称,我这里只是用来做实验说明这个效果,哈哈~~~)

静态成员函数示例代码

静态成员函数特点与静态成员变量类似,所有对象共享一份,不属于任何一个对象!同样也可以不用创建对象,通过类名访问

上面介绍特点的时候说过,静态成员函数只能访问静态成员变量,因此它不能访问非静态成员变量了,这又是为什么呢?

先看看这段代码,有没有问题?

class Sta
{
public:
	int _b;

private:
	static int s_a; //类内声明
	//static int sta_display() { return s_a; }
	static int sta_display() { return _b; }

};

int Sta::s_a = 0; //类外初始化,初始化不加static关键字,否则编译不通过

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指针指向谁?逻辑上行不通了。

所以静态成员函数只能老老实实访问静态成员变量反正静态成员变量不属于任何对象,正好静态成员函数也不能提供任何对象!上面代码注释行是行得通的!

//static int sta_display() { return s_a; }

访问权限

补充一点:若像上面那个Sta类那样将静态成员变量、函数声明为private(私有作用域)的话,类外是不可访问的。虽然它们是共享的,但也有访问权限。既开放(类内),又关闭(类外)!真银杏~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值