类的静态成员

类的静态成员

静态成员是解决同一类的不同对象之间数据和函数共享问题的

如果某个属性为整个类所共有,不属于任何一个具体对象,则采用static关键字来声明为静态成员。静态成员在每个类只有一个副本,由该类的所有对象共同维护和使用,从而实现了同一类的不同对象之间的数据共享

静态数据成员

在书本之前提到的Point类中若想加入表示用于统计Point类的对象个数便可用到静态数据成员来解决问题,例如:

#include<iostream>
using namespace std;

class Point{
public:
	Point(int x=0,int y=0):x(x),y(x){
		//每构造一个点,计数器加一
		count++;	
	}
	Point(Point &p){
		x=p.x;
		y=p.y;
		count++;//复制构造函数每被调用一次,计数器加一
	}
	~Point(){count--;}//相对应的,Point类的一个对象消亡的时候,点数减一
	int getX(){return x;}
	int getY(){return y;}
	void showCount(){
		cout<<"  Object count="<<count<<endl;	
	}
private:
	int x,y;
	static int count;//静态数据成员,记录点数
};

int Point::count=0;

int main(){
	Point a(4,5);//构造点a,点数将会加一
	cout<<"Point A:"<<a.getX()<<","<<a.getY();
	a.showCount();
	
	Point b(a);//通过点a复制构造点b,点数加一
	cout<<"Point B:"<<b.getX()<<","<<b.getY();
	b.showCount();
	cout<<"Point类的对象所占字节数:"<<sizeof(Point)<<endl;//实验观察静态数据成员的属性
	return 0;
}

运行结果:

可以看出:

  • 1、达到了计算点数的功能,创建a点后count的值为1,复制构造点b后count的值为2;
  • 2、我通过sizeof运算符得出了Point类的一个对象占有8个字节,但一个对象的数据成员由三个int型的x,y,和count,一个int型的数据所占字节数为4,这三个int型变量之间的不同点在于count是用static定义的静态数据,这就说明了所得的8个字节是x和y的,静态数据count就是所有对象共同维护和使用的数据,这就是计算得出的字节数为8不为12原因。

静态函数成员

上面的例子完成了统计点数的功能,但其局限性在于count的值只能通过对象调用函数来输出,当没有对象时,即点数为零,我们就无法输出count的值,这就与我们赋予这个值的意义(为整个类所共有不属于任何对象)相背离。我们想要使共有的属性在使用权限上完全脱离对象的束缚

方案一

直接通过类名调用函数,来输出点数的初始值,main函数修改如下:

int main(){
	Point::showCount();//希望能够输出点数的初始值
	Point a(4,5);//构造点a,点数将会加一
	cout<<"Point A:"<<a.getX()<<","<<a.getY();
	a.showCount();
	
	Point b(a);//通过点a复制构造点b,点数加一
	cout<<"Point B:"<<b.getX()<<","<<b.getY();
	b.showCount();
	cout<<"Point类的对象所占字节数:"<<sizeof(Point)<<endl;//实验观察静态数据成员的属性
	return 0;
}

运行结果:

发现出现了编译错误,原因表示非静态函数成员showCount的引用必须和相应的对象结合,方案一行不通

方案二

既然非静态函数必须和对象结合,那么使用静态函数成员呢?
所谓静态成员函数就是使用static关键字声明的函数成员,和静态数据成员一样属于整个类,同一个类的对象共同拥有,为这些对象所共享。它既可以通过类名调用也可以通过对象名调用,接下来实验证明
将Point类外部接口中的showCount函数改为:

stactic void showCount(){
	cout<<"  Object count="<<count<<endl;
}

并将main函数改为:

int main(){
	Point::showCount();//看是否能输出点数的初始值
	Point a(4,5);//构造点a,点数将会加一
	cout<<"Point A:"<<a.getX()<<","<<a.getY();
	Point::showCount();
	
	Point b(a);//通过点a复制构造点b,点数加一
	cout<<"Point B:"<<b.getX()<<","<<b.getY();
	Point::showCount();
	cout<<"Point类的对象所占字节数:"<<sizeof(Point)<<endl;//实验观察静态数据成员的属性
	return 0;
}

运行结果:

可以看出,已经成功地输出了点数的初始值,构造点a和复制构造点b后的点数也相应地输出,所以说我们的静态函数的目的达到了,让点数这一属性属于整个类,可以直接通过类而不需要再通过对象引用函数。


下面我们来实验用对象调用静态函数,看之前说的是否能行,在设置了静态函数后仍然使用之前的main函数:

int main(){
	Point::showCount();//输出点数的初始值
	Point a(4,5);//构造点a,点数将会加一
	cout<<"Point A:"<<a.getX()<<","<<a.getY();
	a.showCount();//通过对象调用静态函数
	
	Point b(a);//通过点a复制构造点b,点数加一
	cout<<"Point B:"<<b.getX()<<","<<b.getY();
	b.showCount();//通过对象调用静态函数
	cout<<"Point类的对象所占字节数:"<<sizeof(Point)<<endl;//实验观察静态数据成员的属性
	return 0;

运行结果:

同样成功!

posted @ 2019-09-22 15:53  Wybie  阅读(478)  评论(0编辑  收藏  举报