类的静态成员为类创建的所有对象所共有的成员,不单独属于某一对象,而属于整个类,而静态成员分为静态成员变量、静态成员函数。
静态成员变量(静态数据成员):
引入及解决问题的优势:
类创建了多个对象,对象的具体成员对象各不相干,而在大量对象的基础上,出现了一部分共有属性的对象
(例如:
1、银行系统中,用户作为单独对象时,成员变量中,银行储存利率为所有用户公有且一致的对象成员;
2、班级系统所有同学作为单独变量,需统计班级莫科目总分,该成员属于全体公有,不属于单一对象)
由上面引例了解到以上两种情况如设置为普通对象的成员:
例1:浪费了大量地址空间去存储一致的对象成员
例2:全班总分数对每一个同学单一的对象而言成员没有实际意义,而在每位同学对象依次录入成绩的同时总成绩变化,如何更改之前每个对象的总成绩?引发大量重复修改值的操作
因此优化引出静态成员变量的概念:
- 多个同类对象共用静态成员变量,节约空间
- 多个同类对象共用静态成员变量,一改全改便于维护
静态成员变量的定义及初始化:
声明(类内):
static 类型名 静态成员变量名;
定义、初始化(类外):
类型 类名::静态成员变量 = 初始化值;//初始化
在初始化时需要区分静态变量是否为整数类型,不同的类型决定了初始化位置不同。
- 整数类型的静态成员变量可以在定义或声明中的某一处完成初始化,但不能同时在两处进行初始化,即便初始化的值是相同的也不行。
- 非整数类型的静态成员变量则必须且只能在定义语句中进行初始化,类内的声明语句中不允许初始化操作。
- 类内声明,类外初始化定义
//1.如何对静态成员变量进行初始化? // class A { //静态成员变量类型为整型: //可以在声明处初始化(仅静态常量!),也可在定义处初始化 const static int a = 10; //仅静态常量! static int b;//普通静态成员变量只能在类外初始化 //静态成员变量类型非整型,只能在类外定义处初始化 static string c; }; int A::b = 10; string A::c = "hello";
注意:
- 静态成员变量在类外初始化,不能在类内构造函数初始化;
- 因为静态成员变量不属于某一个对象,而单属于类(或全体对象),普通成员在类内的构造函数内初始化,二者需区分开;
- 如果可以在类的构造函数中初始化,那么每创建一个对象,静态成员变量就要被初始化一次,这显然是错误的;
- 静态成员变量仅在 定义的时有static,初始化时没有static;
- 静态成员变量为私有类型,在类外初始化,类外并不在类外成员函数内,所以满足private访问规则;
- 初始化时使用作用域运算符标明所属类。
静态成员变量的使用
类外函数使用静态成员对象时,需得更改静态成员变量的私有属性改为公有public属性方可使用
//静态成员变量属于类,因此可以通过类名对它进行访问。访问形式为:
类名::成员变量;
//也可以通过对象名访问,访问形式为:
对象名.静态成员变量;
//编译器通过对象能推出类类型。
引例:上例2、班级系统所有同学作为单独变量,需统计班级某科目总分
//这是配置好的模板文件
#include <iostream>
#include <string>
using namespace std;
class Stu
{
private:
string name;
string num;
int grade;
public:
static int sum;//静态成员对象的定义
Stu(string na = "XX", string nu="XXXX", int g=90) :name(na), num(nu), grade(g)
{
sum += grade;
};
};
int Stu::sum = 0;//静态成员对象初始化
int main()
{
Stu stu[5]{ {"李华","211",98},{"刘明","212",88},{"王雅","213",66},{"乔伊","214",77},{"曹颖","215",97} };
cout << "总成绩为:" << Stu::sum << endl;//前提静态成员变量为public公有访问权限下,私有错误
cout << "总成绩为:" << stu[0].sum << endl << endl;
Stu stu2{ "陆雅","216",100 };//一改全改
cout << "添加新成绩:100,一改全改:"<<endl;
cout << "总成绩为:" << stu[0].sum << endl;
cout << "总成绩为:" << stu[1].sum << endl;
cout << "总成绩为:" << stu[2].sum << endl;
cout << "总成绩为:" << stu[3].sum << endl;
cout << "总成绩为:" << stu[4].sum << endl;
cout << "总成绩为:" << stu2.sum << endl;
return 0;
}
输出:
静态成员函数:
主要是为了处理静态成员数据。
静态成员函数可以在类内定义,也可以在类外定义(静态成员变量只能类内声明,类外定义初始化)
在类外定义时,不加static
在类内声明格式为:
static 返回类型 静态成员函数名(参数表);
通过类名调用:
类名::静态成员函数名(实参表); //在类外访问必须是public
通过对象名调用:
对象名.静态成员函数名(实参表);//在类外访问必须是public,编译器通过对象能推出类类型。
当调用一个对象的非静态成员函数时,系统会把该对象的起始地址赋予成员函数的this指针。而静态成员函数不属于某一对象,因此它没有this指针。由此可以得出:
静态成员函数不能访问类的非静态成员(包括非静态成员变量和非静态成员函数)。即需要用到this指针的地方静态成员函数是不能访问的。
引例:
#include <iostream>
#include <string>
using namespace std;
class Student //定义Student类
{
private:
string m_name; //姓名
string m_num; //学号
float m_score; //分数
static float sum; //分数总和
static int count; //学生总数
public:
Student(string name,string num, float s) :m_name(name), m_num(num), m_score(s)
{
sum += m_score; //计算总分
count++; //累统计总人数
}
static float average(); //声明静态成员函数
};
float Student::average() //定义静态成员函数
{
return(sum / count);
}
float Student::sum = 0; //对静态成员变量初始化
int Student::count = 0; //对静态成员变量初始化
int main()
{
Stu stu[5]{ {"李华","211",98},{"刘明","212",87},
{"王雅","213",66},{"乔伊","214",77},{"曹颖","215",97} };
};
cout << "学生的平均成绩为:" << Student::average() << endl;//调用静态成员函数
return 0;
}