C++类中的静态成员

静态数据成员

我们知道全局变量是可以在文件中共享的,但是用全局变量时,安全性却得不到保证,因为在文件中的任何地方都可以自由的修改全局变量,很可能造成误操作,导致程序的错误。

如果,我们想在同类个多个对象之间实现数据共享,可以不使用全局变量,而使用静态数据成员的。

静态数据成员是一种特殊的成员,它一static开头:

===========示例代码1.1==========================

class Box
{
	public:
		int volume();
	private:
		static int height;//把height定义为静态数据成员 
		int width;
		int lenth;
}
如果希望各对象中的height值是一样的,就可以把它定义为静态数据成员,这样它就为各对象所共有,而不只属于某一个对象,所有的对象都可以引用它。并且,如果将静态数据成员声明为静态的常数据成员,那么各对象就只可以引用,而不可以改变它的值;如果声明为普通的静态数据成员(代码1.1中的就是普通的静态成员),那么各对象既可以访问该数据成员,又可以改变该数据成员。

说明:

(1)如果值声明了类而未定义对象,则类的一般数据成员是不占内存空间的,只有在定义对象时,才为对象的数据分配内存空间。但是静态数据成员不属于某一个对象,在为对象所分配的空间中,不包括静态数据成员所占的空间。静态数据成员是在类定义的时候,就在独立于任何一个对象之外的地方,分配了相应的存储空间。因此,只要定义了静态数据成员,及时不定义对象,也可以为静态数据成员分配空间,也可以访问和使用。在一个类中可以有一个或多个静态数据成语昂,所有的对象共享这些静态数据成员,都可以引用它。

(2)静态数据成员在程序编译的时候,被分配空间,到程序结束的时候才释放空间。

(3)静态数据成员可以初始化,但只能在类体外进行初始化,如果静态数据成员被定义成私有的,则不能再类外直接引用,而必须通过公用的成员函数引用。

其一般形式:

int Box::height=10;//表示对Box类中的数据成员初始化
其一般形式为:

数据类型    类名::静态数据成员名=初值;

不必在初始化语句中加static,不能用参数初始化表对静态数据成员初始化。

如果未对静态数据成员赋初值,则编译系统会自动赋予初值0。

(4)静态数据成员既可以通关过对象名来引用,也可以通过类名来引用。

==============示例代码1.2=============================

#include<iostream>
using namespace std;
class Box
{
	public:
		int volume();
		Box(int w,int l);
		static int height;//把height定义为静态数据成员 
		int width;
		int length;
};
Box::Box(int w,int l)
{
	width=w;
	length=l;	
} 
int Box::volume()
{
	return (height*width*length);
} 
int Box::height=10;//经静态数据成员初始化 
int main()
{
	Box a(15,20),b(20,30);
	cout<<a.height<<endl;//通过对象a引用静态数据成员
	cout<<b.height<<endl;//通过对象b引用静态数据成员
	cout<<Box::height<<endl;//通过类名引用静态数据成员
	cout<<b.volume()<<endl;//调用volume函数,求b的体积 
	return 0;
}

运行结果:


静态成员函数

成员函数也可以定义为静态的,在类中声明函数的前面加static就成了静态成员函数

static int volume();

和静态数据成员一样,静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公用的静态成员函数,要用类名和域运算符“::”。

Box::volume();

实际上,也允许通过对象名调用静态成员函数,

a.volume();

这并不以为着此函数是属于对象a的。

与静态数据成员不同,静态成员函数的作用不是为了对象之间的沟通,而是为了处理静态数据成员。

静态成员函数和非静态成员函数的区别是:非静态成员函数有this指针,而静态成员函数没有this指针。

(有关this指针,可以看下C++中的对象指针

静态成员函数可以银哟个本类中的静态数据成员,因为静态数据成员同样是属于类的,可以直接引用。

在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。例如,在一个静态成员函数中,有以下语句:

cout<<height<<endl;//若height已声明为static,则引用本类中的静态成员,合法
但是,并不是绝对不能引用本类中的非静态成员,只是不能默认访问,因为无法知道应该去找那个对象。如果一定要引用本类中的非静态成员,应加对象名和成员运算符。

cout<<a.width<<endl;//引用本类对象a中的非静态成员
假设a已定义为Box类对象,且在当前作用域内有效,则此语句合法。

虽然上述方法可行,但是我们一般不在静态成员函数中引用非静态的数据成员,只引用静态数据成员,这样逻辑上更加清楚,可读性高。

================示例代码2.1=============

#include<iostream>
using namespace std;
class Student
{
	public:
		Student(int n,int a,float s):num(n),age(a),score(s){}//定义构造函数
		void total();
		static float average();//声明静态成员函数
	private:
		int num;
		int age;
		float score;
		static float sum;     //静态数据成员sum 
		static int count;     //静态数据成员count 
};
void Student::total()         //定义非静态成员函数 
{
	sum+=score;				  //累加总分
	count++;				  //累计已统计人数	
}
float Student::average()	  //定义静态成员函数 
{
	return(sum/count);
} 
float Student::sum=0;			//对公用静态数据成员sum初始化
int Student::count=0;			// 对公用静态数据成员count初始化
int main()
{
	Student stud[5]={		    //定义对象数组并初始化 
		Student(1001,18,70),
		Student(1002,19,78),
		Student(1003,10,100),
		Student(1004,19,100),
		Student(1005,17,98)
	};
	int n;
	cout<<"Please input the number of students:";
	cin>>n;						//输入需要求前面多少名学生的平均成绩
	for(int i=0;i<n;i++)
	{
		stud[i].total();		//调用n次total函数 
	} 
	cout<<"The average score of "<<n<<"students is "<<Student::average()<<endl;
								//调用静态成员函数
	return 0; 
	
} 

运行结果:

分析:

toal是公有的成员函数,其作用是将一个学生的成绩累加到sum中。共有的成员函数可以引用本对象中的一般是数据成员(非静态数据成员),也可以引用类中的静态数据成员。score是非静态数据函数,num和count是静态数据成员。

average是静态数据成员,它可以直接引用私有的静态数据成员(不必加对象名),函数返回成绩的平均值。

在main函数中,引用total函数要加对象名,引用静态成员函数average要用类名(或对象名)。


静态数据成员和成员函数是属于类的,是在定义类的时候就定义并分配存储空间的。

非静态的数据成员和成员函数是属于对象的(可以通过this指针调用),是在定义对象的时候进行定义和分配存储空间的。

一般情况下,最好使用静态的成员函数调用静态的成员变量,用非静态的成员函数调用非静态的成员变量。

如果在静态成员函数中使用非静态数据成员的话,要用相应的对象进行调用:

cout<<a.lenth<<endl;

如果在非静态数据函数中调用静态数据成员的话,应该加上类的限定

cout<<"height:"<<Box::height<<endl;

to be honset, you can use height instead of "Box::height". but we don't recommend to do that. 


在C++程序中,最好养成这样的习惯:

只用静态成员函数引用静态数据成员,而不引用非静态数据成员

posted @ 2013-09-08 12:26  千手宇智波  阅读(331)  评论(0编辑  收藏  举报