在 C++中,静态成员是属于整个类的而不是某个对象,静态成员变量只存储一份供 所有对象共用。所以在所有对象中都可以共享它。使用静态成员变量实现多个对象之间 的数据共享不会破坏隐藏的原则,保证了安全性还可以节省内存。
1.静态成员变量
类的静态成员,属于类,也属于对象,但终归属于类。
//声明
static 数据类型 成员变量; //在类的内部
//初始化
数据类型 类名::静态数据成员 = 初值;//在类的外部
//调⽤用
类名::静态数据成员
类对象.静态数据成员
class AA
{
public:
AA(int a,int b)
{
m_a = a;
m_b = b;
}
int getC(){
cout<<"c = "<<m_c<<endl;
return m_c;
}
static int m_c;//静态的成员变量
//1.在类的内部声明这个变量 用static
//静态的成员变量是堆本类共享 的,所有本类中的对象,都是公用一个内存区域,如图1
private:
int m_a;
int m_b;
}
//2.静态成员变量必须被初始化,在类的外部去写,它是在全局区开辟空间的
int AA::m_c = 0;
int main(void)
{
AA aa1(10,20),aa2(100,200),aa3(1000,2000);
aa1.getC();//0
aa2.getC();//0
aa3.getC();//0
//怎么去修改一个静态的成员变量
AA::m_c = 200;
aa1.getC();//200
aa2.getC();//200
aa3.getC();//200
return 0;
}
1.png
2.静态成员函数
//声明
static 函数声明
//调用
类名::函数调用
类对象.函数调用
class Student
{
public:
Student(int num,double score){
m_num = num;
m_score = score;
count++;
sum_score +=score;
}
static double getAvg(){
return sum_score/count;
}
private:
int m_num;//学号
double m_score;//成绩
static int count;//记录目前Student类已经创建了多少个学生对象
static double sum_score;//所有已经定义学生对象的总score和
};
//在类的外面初始化成员变量
int Student::count = 0;
double Student::sum_score = 0.0;
int main(void){
Student s1(1,100);
Student s2(2,90);
Student s3(3,80);
//使用一个静态的成员函数
double avg = Student::getAvg();//可以把他当做一个类的全局函数
cout<<"平均分为:"<<avg<<endl;
return 0;
}
3.总结
3.1静态成员变量
1 static 成员变量实现了同类对象间信息共享。
2 static 成员类外存储,求类大小,并不包含在内。
3 static 成员是命名空间属于类的全局变量,存储在 data 区。
4 static 成员只能类外初始化。
5 可以通过类名访问(无对象生成时亦可),也可以通过对象访问。
3.2静态成员函数
- 静态成员函数的意义,不在于信息共享,数据沟通,而在于管理静态数据成员, 完成对静态数据成员的封装。
- 静态成员函数只能访问静态数据成员。原因:非静态成员函数,在调用时this 指针被当作参数传进。而静态成员函数属于类,而不属于对象,没有 this 指针。
4.编译器堆属性和方法的处理机制
class C1
{
public:
int i;//4
int j;//4
int k;//4
};//12
class C2
{
public:
int i;
int j;
int k;
static int m; //4
public:
int getK() const{return k;}//4
void setK(int val) {k = val;}//4
};
struct S1{
int i;
int j;
int k;
};//12
struct S2
{
int i;
int j;
int k;
static int m;
};//12?
int main()
{
cout<<"c1:"<<sizeof(C1)<<endl;//12
cout<<"c1:"<<sizeof(C2)<<endl;//12
cout<<"c1:"<<sizeof(S1)<<endl;//12
cout<<"c1:"<<sizeof(S2)<<endl;//12
return 0;
}
通过上面的案例,我们可以的得出:
C++类对象中的成员变量和成员函数是分开存储的
成员变量:
普通成员变量:存储于对象中,与struct变量有相同的内存布局和字节对齐方式
静态成员变量:存储于全局数据区中
成员函数:存储于代码段中。
---------------------------------------------------------
1、C++类对象中的成员变量和成员函数是分开存储的。C语言中的内存四区模
型仍然有效!
2、C++中类的普通成员函数都隐式包含一个指向当前对象的this指针。
3、静态成员函数、成员变量属于类
4、静态成员函数与普通成员函数的区别
静态成员函数不包含指向具体对象的指针
普通成员函数包含一个指向具体对象的指针
5.强化练习-static仓库进货出货
某商店经销一种货物。货物购进和卖出时以箱为单位,各箱的重量不一样,因此,商店需要记录目前库存的总重量。现在用C++模拟商店货物购进和卖出的情形
/*
static
*/
class Goods
{
public:
Goods(){
weight = 0;
next = NULL;
cout<<"创建了一个货物,重量是0"<<endl;
}
//有参数的构造函数
Goods(int w){
weight = w;
next = NULL;
//每创建一个货物 总重量应该加
cout<<"创建了一个货物,重量是"<<w<<endl;
total_weight += w;
}
//提供一个静态的成员函数来访问静态成员
static int getTotal(){
return total_weight;
}
~Goods()
{
cout<<"删除了一项重量是"<<weight<<"的货物"<<endl;
total_weight -= weight;
}
//给货物类编程一个链表的节点
Goods *next;
private:
int weight;//货物重量
static int total_weight;//所有货物的总重量
}
int Goods::total_weight = 0;
//进货的方法
void buy(Goods* &head,int w)//Goods *的引用就是Goods**
{
//创建一个新的货物
Goods *new_goods = new Goods(w);//通过new在堆上开辟空间,调用了Goods类的有参构造函数
if(head == NULL){//如果head是空
head = new_goods;
}
else{
//如果head不为空,从head表头添加
new_goods->next = head;
head = new_goods;
}
}
//出货的方法
void sale(Goods* &head)
{
if(head == NULL){
cout<<"仓库已经没有货物了"<<endl;
return ;
}
Goods *temp = head;
head = head->next;
delete temp;
cout<<"saled"<<endl;
}
int main(void)
{
int choice = 0;
Goods *head = NULL; //这是所有货物的表头
do{
cout<<"1 进货"<<endl;
cout<<"2 出货"<<endl;
cout<<"0 退出"<<endl;
cin>>choice;
switch(choice)
{
case 1://进货
cout<<"请输入要创建的货物的重量"<<endl;
int w;
cin>>w;
buy(head,w);
break;
case 2://出货
sale(head);
break;
case 0:
return 0;
break;
default:
break;
}
cout<<"此时仓库中有"<<Goods::total_weight<<"重量的货物"<<endl;
}while(1);
return 0;
}
网友评论