静态成员static详解

昨天面试蔚来的C++岗位的时候,不可避免的问道static关键字的东西,奈何之前只是一知半解,只了解个大概,所以就被这个问题卡住了,所以今天索性就彻底把这个问题搞清楚~

关于静态成员

  • 静态数据成员
  • 静态函数成员
  • 静态常量成员

静态数据成员

  • 对象是类的实例,类中说明的数据成员在该类的每个对象中都有一个副本。有时,类的对象可能需要共享一些信息。例如,在一个银行系统中,最主要的对象是一个个的账户,为此需要定义一个账户类。每个账户包含的信息有账号、存入日期、存款金额等。为了计算账户的利息,还需要知道利率。利率是每个账户对象都必须知道的信息,而且对所有账户类的对象,这个值是相同的。因此不必为每个对象设置这样一个数据成员,只需让所有的对象共享这样一个值就可以了。
  • 共享信息一般用全局变量来表示,但如果用全局变量来表示这个共享数据,则缺乏对数据的保护。因为全局变量不受类的访问控制的限定,除了类的对象可以访问它以外,其他类的对象以及全局函数往往也能读取这些全局变量。同时也容易和其他的名字相冲突。
  • 如果可以把一个数据当做全局变量去存储,但又被隐藏在类中,并且清楚地表示与这个类之间的联系,那是最理想的。

这个功能可以通过静态数据成员来实现。类的静态数据成员拥有一块单独的存储区,而不管创建了多少个该类的对象。所有这些对象的静态数据成员都共享这一块空间。但静态数据成员是属于类的,它的名字只在类的范围内有效,并且可以是公有的或私有的,这又使他免受其他全局函数的干扰。

要将一些数据成员说明为静态的,只需要在此数据成员前加关键字static
银行账户类的定义
class SavingAccount {
private:
	char AccountNumber[20];   // 账号
	char SavingDate[8];  // 存款日期,格式为YYYYMMDD
	double balance;     // 存款额
	static double rate;  // 利率,为静态数据成员(类内声明)
}double SavingAccount::rate = 0.5; // 类外初始化

类定义只是给出了对象构成的说明,真正的存储空间是在对象定义时分配的。但由于静态数据成员是属于类而不属于对象,因此系统为对象分配空间时,并不包括静态数据成员的空间。所以,静态数据成员的空间必须单独分配,而且必须只分配一次。为静态数据成员分配空间成为静态数据成员的初始化(定义)。静态数据成员的初始化一般出现在类的实现文件中。

静态数据成员是属于类的,因此可以通过作用域::静态数据成员名。但从每个对象的角度来看,它似乎又是对象的一部分,因此又可以和普通的成员一样用对象引用它。但不管哪个对象,引用的都是同一块空间。

静态成员函数

  • 像静态数据成员一样,成员函数也可以是静态的。
  • 静态成员函数用于操作静态数据成员,它是为类而不是类的对象服务的。
  • 静态成员函数所做的操作将影响类的所有对象,而不是某一特定对象。把这样的函数放在类的内部,就不需要定义一个全局函数,减少了全局名字空间的占用。

静态成员函数的声明只需要在类定义中的函数原型前加上关键字static。
与普通的成员函数一样,静态成员函数的定义可以写在类定义中,也可以写在类定义的外面
在类外定义时,函数定义中不用加static。

  • 静态成员函数可以用对象来调用。然而,更典型的方法是通过类名来调用,即“类名::静态成员函数名()”的形式
  • 静态成员函数是为类服务的,它的最大特点是没有this指针,因此,静态成员函数不能访问一般的数据成员,而只能访问静态数据成员或其他静态成员函数。
  • 定义静态成员函数的主要目的是访问静态数据成员。由于它不属于任何对象,因此,可以在任何对象建立之前用它处理静态数据成员,如初始化静态数据成员的值。这是普通成员函数不能实现的功能。
StaticSample类的定义
// 文件名:StaticSample.h
// 静态数据成员和静态成员函数示例
#ifndef _StaticSample_h
#define _StaticSample_h
#include <iostream>
using namespace std;

class StaticSample {
private:
	static int obj_count;  // 静态数据成员
	static int obj_living;
public:
	StaticSample() {
		++obj_count;
		++obj_living;
	}
	~StaticSample() {
		--obj_living;
	}
	static void display() {
		cout << "总对象数:" << obj_count << "\t存活对象数:" << obj_living << endl;
	}  // 静态成员函数的类内实现
};
#endif // !1
// StaticSample.cpp
#include "StaticSample.h"
int StaticSample::obj_count = 0;
int StaticSample::obj_living = 0;
StaticSample类的使用
// 文件名:Static_Sample.cpp
// Static Sample类的使用
#include "StaticSample.h"

int main() {
	StaticSample::display();  // 通过类名限定调用静态成员函数

	StaticSample s1, s2;
	StaticSample::display();

	StaticSample* p1 = new StaticSample, * p2 = new StaticSample;
	s1.display();  // 通过对象调用静态成员函数

	delete p1;
	p2->display();  // 通过指向对象的指针来调用静态成员函数

	delete p2;
	StaticSample::display();

	return 0;
}
程序的运行结果

图片1

静态常量成员

  • 静态数据成员是整个类共享的数据成员。有时整个类的所有对象需要共享一个常量,此时可以把这个成员设为静态常量成员。静态常量数据成员用关键词static const声明。
  • 注意,常量数据成员和静态常量数据成员的区别。常量数据成员属于各个对象,不同对象的常量数据成员的值是不同的。静态常量数据成员是属于整个类,而不同对象的静态常量数据成员是相同的。
  • 一般而言,类的数据成员不能在类定义时初始化。普通的数据成员是在对象定义时,由构造函数对他们进行初始化的。静态数据成员是在静态数据成员定义时初始化的。这个规则只有一个例外,就是对静态常量数据成员。静态常量数据成员可以并且必须在类定义时初始化。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

loveCC_orange

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值