- 静态成员:为了实现一个类的多个对象之间的数据共享。
- 静态成员包括 静态数据成员 和 静态函数成员。
一、静态数据成员
- 在一个类中若将一个数据成员说明为static,这种成员称为静态数据成员。 与一般的数据成员不同,无论建立多少个类的对象,都只有一个静态数据成员的拷贝。从而实现了同一个类的不同对象之间的数据共享。
- 定义静态数据成员的格式:
static 数据类型 数据成员名
注意:
1、静态数据成员的定义与普通数据成员相似,但前面要加上 static 关键字。例如:
static int count; //静态数据成员,用于统计学生人数
static float sum; //静态数据成员,用于统计累加成绩
static float ave; //静态数据成员,用于统计平均成绩
2、静态数据成员的初始化与普通数据成员不同。静态数据成员的初始化应在类外单独进行,而且应在定义对象之前进行。
一般在主函数 main 之前,类声明之后的特殊地带为它提供定义和初始化。
静态数据成员初始化的格式如下(注意:这时在数据成员名的前面不加static):
数据类型 类名::静态数据成员名=初始值;
例如:
int Student::count=0;
float Student::sum=0.0;
float Student::ave=0.0;
3、静态数据成员属于类(准确地说是属于类对象的集合),而不像普通数据成员那样属于某一对象,因此可以使用 “ 类名:: ” 访问静态的数据成员。
格式如下:
类名::静态数据成员名
例如:
Student::count;
Student::sum;
4、公有的静态数据成员可以在对象定义之前被访问;对象定义后,可以通过对象进行访问公有的静态数据成员。静态数据成员是类的公共数据成员,是对象的共享数据项。
用对象访问静态数据成员的格式如下:
对象名.静态数据成员名;
对象指针->静态数据成员名;
5、私有静态数据成员不能再类外直接访问,必须通过公有的成员函数访问。
6、C++支持静态数据成员的一个重要原因是可以不必使用全局变量。依赖于全局变量的类几乎都是违反面向对象程序设计的封装特性的。静态数据成员主要用作类的所有对象所公用的数据,如统计总数,平均数等。
例 1 :静态数据成员的引例
char *a = new char[20]
new分配内存,这里分配了20个字节,然后返回首地址给a
即a可以看做一个20字节的字符数组,即字符串
参考: https://blog.csdn.net/aaqian1/article/details/83717529
#include<iostream>
#include<string.h>
using namespace std;
class Student{
public:
Student(char *name1,char *stu_no1,float score1); //声明构造函数
~Student(); //声明析构函数
void show(); //输出姓名、学号和成绩
void show_count_sum_ave(); //输出学生人数和平均成绩
private:
char *name; //学生姓名
char *stu_no; //学生学号
float score; //学生成绩
int count; //学生人数
float sum; //累加成绩
float ave; //平均成绩
};
Student::Student(char *name1,char *stu_no1,float score1){ //定义构造函数
name=new char[strlen(name1)+1]; //为了最后的'\0'留下位置
strcpy(name,name1);
stu_no=new char[strlen(stu_no1)+1];
strcpy(stu_no,stu_no1);
score=score1;
++count; //累加学生人数
sum=sum+score; //累加成绩
ave=sum/count; //计算平均成绩
}
Student::~Student(){
delete []name;
delete []stu_no;
--count;
sum=sum-score;
}
void Student::show(){
cout<<"\n姓名:"<<name;
cout<<"\n学号:"<<stu_no;
cout<<"\n成绩:"<<score;
}
void Student::show_count_sum_ave(){
cout<<"\n学生人数:"<<count;
cout<<"\n平均成绩:"<<ave;
}
int main(){
Student stu1("李明","01",90); //建立第 1 个学生对象stu1
stu1.show();
stu1.show_count_sum_ave();
cout<<"\n------------------\n";
Student stu2("王晓红","02",88); //建立第 2 个学生对象stu2
stu2.show();
stu2.show_count_sum_ave();
cout<<"\n------------------\n";
Student stu3("吴晓刚","03",90); //建立第 1 个学生对象stu1
stu3.show();
stu3.show_count_sum_ave();
return 0;
}
这个是错误的,因为一个学生对象的count,sum和ave仅仅属于这个学生对象,而不是所有学生对象所共享的,因此它们不能表示所有学生的人数、累加成绩和平均成绩。
例 2 :静态数据成员的使用
#include<iostream>
#include<string.h>
using namespace std;
class Student{
public:
Student(char *name1,char *stu_no1,float score1); //声明构造函数
~Student(); //声明析构函数
void show(); //输出姓名、学号和成绩
void show_count_sum_ave(); //输出学生人数和平均成绩
private:
char *name; //学生姓名
char *stu_no; //学生学号
float score; //学生成绩
static int count; //静态成员函数,学生人数
static float sum; //静态成员函数,累加成绩
static float ave; //静态成员函数,平均成绩
};
Student::Student(char *name1,char *stu_no1,float score1){ //定义构造函数
name=new char[strlen(name1)+1]; //为了最后的'\0'留下位置
strcpy(name,name1);
stu_no=new char[strlen(stu_no1)+1];
strcpy(stu_no,stu_no1);
score=score1;
++count; //累加学生人数
sum=sum+score; //累加成绩
ave=sum/count; //计算平均成绩
}
Student::~Student(){
delete []name;
delete []stu_no;
--count;
sum=sum-score;
}
void Student::show(){
cout<<"\n姓名:"<<name;
cout<<"\n学号:"<<stu_no;
cout<<"\n成绩:"<<score;
}
void Student::show_count_sum_ave(){
cout<<"\n学生人数:"<<count;
cout<<"\n平均成绩:"<<ave;
}
int Student::count=0; //静态数据成员count初始化
float Student::sum=0.0; //静态数据成员sum初始化
float Student::ave=0.0; //静态数据成员ave初始化
int main(){
Student stu1("李明","01",90); //建立第 1 个学生对象stu1
stu1.show();
stu1.show_count_sum_ave();
cout<<"\n------------------\n";
Student stu2("王晓红","02",88); //建立第 2 个学生对象stu2
stu2.show();
stu2.show_count_sum_ave();
cout<<"\n------------------\n";
Student stu3("吴晓刚","03",90); //建立第 1 个学生对象stu1
stu3.show();
stu3.show_count_sum_ave();
return 0;
}
例 3:公有静态成员函数的访问
#include<iostream>
using namespace std;
class Myclass{
public:
static int i;
int geti(){
return i;
}
};
int Myclass::i=0; //静态数据成员初始化,不必在前面加static
int main(){
Myclass::i=200;
Myclass ob1,ob2;
cout<<"ob1.i="<<ob1.geti()<<endl;
cout<<"ob2.i="<<ob2.geti()<<endl;
ob1.i=300;
cout<<"ob1.i="<<ob1.geti()<<endl;
cout<<"ob2.i="<<ob2.geti()<<endl;
return 0;
}
执行结果如下:
所以,静态数据成员也是类的公共数据成员,是对象的共享数据项。
二、静态成员函数
- 在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数属于整个类,是该类所有对象共享的成员函数,而不属于类中的某个对象。
- 定义静态成员函数的格式:
static 返回类型 静态成员函数名(参数表); - 与静态数据成员类似,调用公有静态成员函数的一般格式有如下几种:
类名::静态成员函数名(实参表)
对象.静态成员函数名(实参表)
对象指针->静态成员函数名(实参表)
注意:
1、一般情况下,静态函数成员主要用来访问静态数据成员。当它与静态数据成员一起使用时,达到了对同一类中对象之间数据共享的目的。
2、私有静态成员函数不能做类外部的函数和对象访问。
3、使用静态成员函数的一个原因是,可以用它在建立任何对象之前调用静态成员函数,以处理静态数据成员,这是普通成员函数不能实现的功能。例如:
int main(){
Small_cat::total_disp(); //可以用它在建立任何对象之前调用静态成员函数
Small_cat w1(0.2),w2(0.3),w3(0.4);
·
·
·
return 0;
}
4、编译系统将静态成员函数限定为内部连接。即与现行文件相连接的其他文件中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性。
5、静态成员函数是类的一部分,而不是对象的一部分。如果要在类外调用公有的静态成员函数,使用如下格式较好:
类名::静态成员函数名
如果定义了这个类的对象(例如w1),使用 对象名.静态成员函数名 也是正确的。
6、静态成员函数与非静态成员函数的重要区别是:非静态成员函数有this指针,而静态成员函数没有this指针。
一般而言,静态成员函数不访问类中的非静态成员,可以直接访问本类中的静态数据成员。
若确实需要访问非静态数据成员,静态成员函数只能通过对象名(或对象指针,对象引用)访问该对象的非静态成员。
例 4 :静态成员函数访问静态数据成员
#include<iostream>
using namespace std;
class Small_cat{
public:
Small_cat(double w); //声明构造函数
void display(); //声明非静态成员函数
static void total_disp(); //声明静态成员函数
private:
double weight; //普通数据成员,表示一只小猫的重量
static double total_weight; //静态数据成员,用来累计小猫的重量
static double total_number; //静态数据成员,用来累计小猫的只数
};
Small_cat::Small_cat(double w){ //定义构造函数
weight=w;
total_weight+=w; //累加小猫的重量
total_number++; //累加小猫的只数
}
void Small_cat::display(){ //定义非静态成员函数
cout<<"这只小猫的重量是:"<<weight<<"千克\n"; //显示每只小猫的重量
}
void Small_cat::total_disp() //定义静态成员函数,显示小猫的只数和总重量
//在这里不要使用 static 前缀
{
cout<<total_number<<"只小猫的重量是:";
cout<<total_weight<<"千克"<<endl;
}
//静态成员函数初始化
double Small_cat::total_weight=0;
double Small_cat::total_number=0;
int main(){
Small_cat w1(0.5),w2(0.4),w3(0.3);
w1.display(); //调用非静态成员函数,显示第 1 只小猫的重量
w2.display(); //调用非静态成员函数,显示第 2 只小猫的重量
w3.display(); //调用非静态成员函数,显示第 3 只小猫的重量
Small_cat::total_disp(); //调用静态成员函数,显示小猫的只数和总重量
return 0;
}
执行结果:
例 4 :静态成员函数访问非静态数据成员
#include<iostream>
using namespace std;
class Small_cat{
public:
Small_cat(double w); //声明构造函数
static void display(Small_cat &w); //声明静态成员函数
static void total_disp(); //声明静态成员函数
private:
double weight; //普通数据成员,表示一只小猫的重量
static double total_weight; //静态数据成员,用来累计小猫的重量
static double total_number; //静态数据成员,用来累计小猫的只数
};
Small_cat::Small_cat(double w){ //定义构造函数
weight=w;
total_weight+=w; //累加小猫的重量
total_number++; //累加小猫的只数
}
void Small_cat::display(Small_cat &w){ //定义静态成员函数, 将对象的引用作为参数,显示每只小猫的重量
cout<<"这只小猫的重量是:"<<w.weight<<"千克\n"; //显示每只小猫的重量
}
void Small_cat::total_disp() //定义静态成员函数,显示小猫的只数和总重量
//在这里不要使用 static 前缀
{
cout<<total_number<<"只小猫的重量是:";
cout<<total_weight<<"千克"<<endl;
}
//静态成员函数初始化
double Small_cat::total_weight=0;
double Small_cat::total_number=0;
int main(){
Small_cat w1(0.5),w2(0.4),w3(0.3);
w1.display(w1); //调用非静态成员函数,显示第 1 只小猫的重量
w2.display(w2); //调用非静态成员函数,显示第 2 只小猫的重量
w3.display(w3); //调用非静态成员函数,显示第 3 只小猫的重量
Small_cat::total_disp(); //调用静态成员函数,显示小猫的只数和总重量
return 0;
}