目录
🟪概述
💡什么是静态成员?
在理解静态成员之前,我们先来回忆一下,什么是类?
类不是一个占有内存的实体,而是一种类型,是现实世界的抽象概括。
其中,每个类的对象都是该类数据成员的拷贝。
但有时我们的需求是:所有对象在类的范围内共享某个成员,也就是说,该成员的属性是类的所有对象共有的。
这时我们将这个成员声明为static
即可。
这种声明为static
的类的成员叫做类的静态成员。
💡如何理解静态成员?
打个比方,我们有一个学生类Student
,其数据成员,可以是name
,Gender
,id
,score
,numStu
(人数)等等。
在这里,我们就可以将学生的人数,即数据成员numStu
声明为static
,因为无论学生类的对象有多少,数据成员numStu
(学生的总人数)都只有一个,所有Student
类的对象都能共享它,并且能够访问它。
💡静态成员会在哪里进行空间分配?
将我们数据成员numStu
声明为static
后,再创建一个Student
的对象stu
。
此时stu
对象并没有随之创建静态数据成员numStu
的内存空间。这是为什么?
事实上,静态成员的内存分配并不会随着类对象的创建而创建,也不会随着对象的消失而消失。也就是说:
静态成员的内存分配,并不在Student
类的构造函数中进行,其空间回收也不在析构函数中完成。
那么,回到问题上来。
静态成员会在哪里进行空间分配?
有三种可能:
- 程序
main()
函数所在的源文件中(全局数据处) - 类的声明文件(作为类的外部接口的头文件)
- 类的定义文件(类的内部实现细节)
我们来分析一下:
- 问:可以在main()函数之前的全局数据定义处,定义静态成员吗?
- 答:不可以!这样会导致每个重用该类的应用程序在包含该类的头文件后,都不得不在应用程序中再定义一下该类的静态成员。这不便于类的重用。
- 问:可以在类的声明文件里分配吗?
- 答:不可以!类的声明文件是不能进行实际的空间分配的(只能进行成员的声明,并不能定义),也就是说,在类的声明文件中写:
static int numStu = 0;
是不对的。
注意:
在头文件中,类声明的外部,进行静态成员的定义,也是不行的,因为这样会导致,在多个使用该类的源文件中,对其进行重复定义。
- 问:可以在类定义的文件中吗?
- 答:可以的。我们应该在类定义文件的内部实现中,定义静态成员。定义时要用类名引导。这样在重用该类时,只需导入类的头文件即可。
例子如下:
Student.h
Student.cpp
main.cpp
- 运行结果如下:
🟥静态成员有哪些分类?
我们知道,类可以分为数据成员和成员函数,同样的,静态成员的分类为:
✨静态数据成员
在类的外部,访问静态数据成员可以是:t1.numStu
或者是t2.numStu
,都是可以的,这表示任意对象都能共享该静态成员。但是通常我们会用Student::numStu
来访问静态成员,其表明该静态数据成员不属于任意一个特定对象,而是属于Student
类的。
静态数据成员的使用场景:
- 用来保存流动变化的对象个数。
- 作为一个标志,指示一个特定动作是否发生。
- 一个指向链表第一个成员或最后一个成员的指针。
✨静态成员函数
静态成员函数的定义位置与一般成员函数一样,属于类定义的一部分。
与静态数据成员一样,静态成员函数也和类相联系,但并不与类的对象相联系,所以访问静态成员函数时,不需要对象引导。但可以用对象来引用静态成员函数。
比如:
需要注意的是:
一个静态成员函数不与任何对象相联系,因此不能对非静态成员进行默认访问。
比如:
在上述例子中,静态成员函数sName()
只认类型,不认对象。
也就是说,对于静态成员函数,任何访问非静态成员的操作都是非法的。
另外,静态成员函数和非静态成员函数的根本区别在于:
- 静态成员函数没有
this
指针。 - 而非静态成员函数有一个指向当前对象的指针
this
🟩写在最后
好了,静态成员就先复习到这里,欢迎大家到评论区一起讨论!