C++学习之静态成员

本文详细解释了在类中使用静态数据成员和静态成员函数的方法,并通过实例展示了如何在不同对象间共享资源的同时保持安全性。文章还强调了静态成员函数与静态数据成员的初始化时机以及它们在类中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.静态数据成员

在类中,有些属性不是类中每个对象分别拥有的,而是共有的。这些共有的属性有些是变化的,如类对象创建的计数值,有些是不变的,如日期类中要用到的12个月的名称。

这些属性不能作为全局变量,因为它们是专属于某个类的。

同时这些属性页不应该是数据成员,因为不能让每个对象都单独拥有它。

对于下列代码:

#include <iostream>
#include <string>

using namespace std;

class Student
{
	int n;
	string name;
public:
	void set(string str)
	{
		static int number = 0;
		name = str;
		n = ++number;
	}

	void print()
	{
		cout << name << " -> students are " << n << " numbers" << endl;
	}
};

void fn()
{
	Student s1;
	s1.set("Jenny");

	Student s2;
	s2.set("Randy");
	s1.print(); 
}

int main()
{
	Student s;
	s.set("Smith");
	fn();
	s.print();

	return 0;
}


输出为:

Jenny -> students are 2 numbers
Smith -> students are 1 numbers


从输出的结果可以看出,结果和我们预期的不同。这主要是由于不同的对象有不同的数据成员n值所致。

那么这个时候需要将学生计数的变量设计为静态成员。这样保证每一个类只有一个实体,每个对象中不再有它的副本。代码实现如下:

#include <iostream>
#include <string>

using namespace std;

class Student
{
	static int number;
	string name;
public:
	void set(string str)
	{
		name = str;
		++number;
	}

	void print()
	{
		cout << name << " -> students are " << number << " numbers" << endl;
	}
};

int Student::number = 0;

void fn()
{
	Student s1;
	s1.set("Jenny");

	Student s2;
	s2.set("Randy");
	s1.print(); 
}

int main()
{
	Student s;
	s.set("Smith");
	fn();
	s.print();

	return 0;
}

该代码输出如下:

Jenny -> students are 3 numbers
Smith -> students are 3 numbers


数据成员设计成静态数据成员后,该成员的变化仍然会在每次对象创建之后的名称赋值后反映出来。该结果存放在专属于Student类名空间的全局数据区中,而不再属于各个Student对象。整个类中只有一份number拷贝,所有对象共享这份拷贝。因此,访问的是唯一的静态数据成员,它不会因对象而异。

由于静态成员脱离对象而存在的性质,所以该实体应在所有对象产生之前存在,因此,在程序启动的时候,需要先对其进行初始化。

定义静态成员的格式不能重复static关键字(int Student::number = 0;)但必须在成员名钱冠以类名加域操作符,以表示该成员的类属。如果不将其初始化,系统将为该成员清0。

2. 静态成员函数

由于如果把静态成员变量设置为公有类型的话,外部就可以直接访问该静态成员变量,这样有失安全性和可维护性,因此与数据成员一样,将静态成员做成私有的,用静态成员函数去访问静态数据成员是适合的。

#include <iostream>
#include <string>

using namespace std;

class Student
{
	static int number;
	string name;
public:
	void set(string str)
	{
		name = str;
		++number;
	}

	static void print_number()
	{
		cout << number << " total numbers" << endl;
	}

	void print()
	{
		cout << name << " -> students are " << number << " numbers" << endl;
	}
};

int Student::number = 0;

void fn()
{
	Student s1;
	s1.set("Jenny");

	Student s2;
	s2.set("Randy");
	s1.print_number(); 
}

int main()
{
	Student s;
	s.set("Smith");
	fn();
	Student::print_number();

	return 0;
}

输出如下:

3 total numbers
3 total numbers


静态成员函数并不受对象的牵制,可以用对象名调用静态成员函数,也可以用类名加上域操作符调用静态成员函数。

静态成员函数的实现位置与成员函数的实现位置应该是一起的。静态成员函数如果不在类中实现,而在类的外部实现时,类名前应免去static关键字,成员函数的静态性只在第一次声明的时候才是必须的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值