C++——静态成员 – 作者:Johnson666

静态成员变量

在类的声明和对象的定义中讲到类包含属性和行为。属性也就是成员变量,它们属于每个对象所有,但对应的数值可以不同。例如学生类中每一个学生都有各自的姓名、学号、性别,这样的成员变量可以称为非静态成员变量。如果某个属性为整个类所有,而不属于任何一个具体的对象,这时就可以用静态成员变量来定义。
使用静态成员变量可以节省内存,因为它是所有对象所共有的。因此,对于多个对象来说,静态成员变量只存储一次,它对每个对象都一样,只要对其进行更新,所有对象都会访问到更新后的变量值。

例子:

#include<string>
#include<iostream>

using namespace std;

class Course
{
public:
	Course(string t,int C_h):type(t),C_hour(C_h)
	{
		Total_hour = Total_hour + C_hour;
	}
	void display();
	static int Total_hour;  //静态成员变量

private:
	string type;
	int C_hour;
};

int Course::Total_hour = 0;  //静态成员变量初始化

void Course::display()
{
	cout << type << '\t' << C_hour;
	cout << "\t当前总学时" << Total_hour << endl;
}

int main()
{
	Course c1 = Course("公共必修课",1024);
	c1.display();
	Course c2 = Course("学科基础课",512);
	c2.display();
	Course c3 = Course("专业必修课",360);
	c3.display();
	Course c4 = Course("专业选修课",160);
	c4.display();
	cout << "总课时为Course::Total_hour:" << Course::Total_hour << endl;
	cout << "c1.Total_hour:" << c1.Total_hour;
	cout << "\tc2.Total_hour:" << c2.Total_hour << endl;
	cout << "c3.Total_hour:" << c3.Total_hour;
	cout << "\tc4.Total_hour:" << c4.Total_hour << endl;
	return 0;
}

结果:
image.png
从上面的例子可以看出,由于总课时Total_hour会随着课程对象的增加而增加,所以将总课时定义为静态成员变量,每次调用构造函数都会对Total_hour进行增加操作,这样就可以达到实时统计总课时的目的。
在利用静态成员变量时需要注意以下几点:
(1)一个类中可以有一个或者多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它们。
(2)类中定义了静态成员变量,即使不定义对象,编译系统也要为它开辟内存空间。静态成员变量不随对象的建立而分配空间,也不随对象的撤销而释放空间,其值也被保留。
(3)静态成员变量可以被初始化,但只能在类体之外初始化,不必在初始化语句中加static关键字,格式如下:
数据类型 类名::静态成员变量名=初值;
初始化时可以赋值,也可以不赋值。如果不赋值,那么会被默认初始化为0.例如上面的例子中也可以这样对Total_hour初始化为0:
int Course::Total_hour; //静态成员变量初始化
此外,还要注意不能用参数初始化表初始化静态成员变量,例如下面的形式就是错误的:
Course(string t,int C_h,int T_h):type(t),C_hour(C_h),Total_hour(T_h){}
(4)静态成员变量既可以通过类名引用,也可以通过对象名引用,但是仍然要遵循private,public和protected的访问控制权限。当通过对象名访问时,对于不同的对象,访问的是同一内存。例如上例中通过Course::Total_hour即类名引用,而c1.Total_hour,c2.Total_hour都是通过对象名引用。但是需要注意这里之所以能在类外进行访问是因为此处的静态成员变量为公有变量。

静态成员函数

普通成员函数需要由对象来进行调用,但是静态成员函数与静态成员变量一样,也属于整个类,归所有对象共同拥有,它的好处在于不依赖任何对象就可以访问静态成员变量。最上面的例子中在未创建对象的情况下,若需要通过普通成员函数输出静态成员变量的初始值则会出现编译错误。

修改最上面的例子,通过普通成员变量输出静态成员变量:

#include<string>
#include<iostream>

using namespace std;

class Course
{
public:
	Course(string t,int C_h):type(t),C_hour(C_h)
	{
		Total_hour = Total_hour + C_hour;
	}
	void display();
	static int Total_hour;  //静态成员变量
	void show_total();  //普通成员函数

private:
	string type;
	int C_hour;
};

int Course::Total_hour = 0;  //静态成员变量初始化

void Course::display()
{
	cout << type << '\t' << C_hour;
	cout << "\t当前总学时" << Total_hour << endl;
}

void Course::show_total()
{
	cout << Total_hour << endl;
}

int main()
{
	Course::show_total();  //通过类名引用普通成员函数,非法
	return 0;
}

结果:
image.png
运行程序发现编译出错,提示“Course::show_total:illegal call of non-static member function”,也就是说普通成员函数必须通过对象进行调用。若修改show_total函数为静态成员函数则可以解决这个问题。即在函数声明处加static进行限定,这样就可以通过对象名调用该函数并输出静态成员变量Total_hour,修改形式如下:
static void show_total();
使用静态成员函数可以方便地引用静态成员变量,但是如果用静态成员函数直接去引用非静态成员变量同样会出问题,这是为什么呢?因为静态成员函数没有this指针,由此决定静态成员函数不能访问本类中的非静态成员变量,除非用对象名.非静态成员变量的形式。也就是说想在show_total函数中引用type,C_hour,则需要通过对象进行访问,例如可对静态成员函数show_total定义修改如下:

void Course::show_total(Course c)
{
    cout << c.type << endl;  //通过对象访问非静态成员变量

来源:freebuf.com 2021-06-17 14:42:38 by: Johnson666

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论