C++学习笔记1——静态成员
来源:互联网 发布:stc8 串口发送数据 编辑:程序博客网 时间:2024/05/16 10:30
静态成员的提出是为了实现一个类的多个对象之间的数据共享。静态成员包括静态数据成员和静态函数成员。
一.静态数据成员
1.先举一个出现错误的代码来作为引例引出静态成员。
#include<iostream>#include<string.h>using namespace std;class Student{ private: char *name; char *stu_no; float score; int count; float sum; float ave; public: Student(char *name1,char *stu_no1,float score1); ~Student(); void show(); void show_count_sum_ave();};Student::Student(char *name1,char *stu_no1,float score1){ name=new char[strlen(name1)+1]; 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(void){ Student stu1("liangxueli","04141108",90); stu1.show(); stu1.show_count_sum_ave(); cout<<"---------------------------------\n"; Student stu2("lijunyi","04141105",80.2); stu2.show(); stu2.show_count_sum_ave(); return 0;}
错误的输出结果为:
姓名:liangxueli学号:04141108成绩:90学生人数:1 //错误结果平均成绩:90 //错误结果---------------------------------姓名:lijunyi学号:04141105成绩:80.2学生人数:1 //错误结果平均成绩:80.2 //错误结果
【分析】本例子的设计思想是,希望每定义一个对象,调用一次构造函数,使数据成员count加1从而累计学生人数,同时用数据成员sum累加学生成绩,求出学生的累加成绩,用数据成员ave计算平均成绩。但是这个例子的运行结果是错误的。其原因是,一个学生对象的count、sum和ave仅仅属于这个学生对象,而不是所有学生对象所共享的,因此它们不能表示所有学生的人数、累加成绩和平均成绩。为了使count、sum和ave被所有的对象共享,可以有两种解决方案。第一个方法是,将count、sum和ave说明为 全局变量。但是,使用全局变量会带来不安全性,并且破坏了面向对象程序设计的信息隐蔽技术,与面向对象的封装性特点是矛盾的。第二个方法就是使用静态数据成员
——在一个类中,若将一个数据成员说明为static,这种成员称为静态数据成员。与一半的数据成员不同,无论建立多少个类的对象,都只有一个静态数据成员的拷贝。从而实现了一个类的不同对象之间的数据共享。
2.静态数据成员的定义如下:
static 数据类型 数据成员名
;
将上例中count、sum和ave改为静态数据成员来处理,过程及结果如下:
#include<iostream>#include<string.h>using namespace std;class Student{ private: char *name; char *stu_no; float score; static int count; static float sum; static float ave; public: Student(char *name1,char *stu_no1,float score1); ~Student(); void show(); void show_count_sum_ave();};Student::Student(char *name1,char *stu_no1,float score1){ name=new char[strlen(name1)+1]; 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;float Student::sum=0.0;float Student::ave=0.0;int main(void){ Student stu1("liangxueli","04141108",90); stu1.show(); stu1.show_count_sum_ave(); cout<<"---------------------------------\n"; Student stu2("lijunyi","04141105",80); stu2.show(); stu2.show_count_sum_ave(); return 0;}(PS:出现了“error: stray ‘\357′ in program”的错误,原因:在程序中输入了全角字符)
正确运行结果:
姓名:liangxueli学号:04141108成绩:90学生人数:1平均成绩:90---------------------------------姓名:lijunyi学号:04141105成绩:80学生人数:2平均成绩:85
3.说明:
1>静态数据成员的定义与普通数据成员相似,但前面要加上static
关键字;
2>静态数据成员的初始化与普通数据成员不同。静态数据成员初始化应在类外单独进行,而且应在定义对象之前进行,一般在主函数main之前,类声明之后的特殊地带为它提供定义和初始化。初始化的格式如下: 数据类型 类名::静态数据成员名=初始值;
注意:这个时候在数据成员名前面不要加static
3>静态数据成员属于类(准确说是属于类对象的集合),而不像普通数据成员那样属于某一个对象,因此可以使用类名::
访问静态的数据成员,例如:
#include<iostream>#include<string.h>using namespace std;class myclass{ public: static int i; int geti() {return i;}};int myclass ::i=0;int main(void){ myclass::i=200;//公有静态数据成员可以在对象定义之前被访问 myclass ob1,ob2; cout<<"successful!\n"<<endl; return 0;}
4>静态数据成员和静态变量一样,是在编译时创建并初始化。它在该类的任何对象被建立之前就存在,因此,公有的静态数据成员可以在对象定义之前被访问(一般给静态数据成员初始化赋值的时候属于定义对象之前的访问),定义对象后,公有的静态数据成员也可以通过对象进行访问: 对象名.静态数据成员名
对象指针->静态数据成员名
;
5>私有静态数据成员不能在类外直接访问,必须通过公有的成员函数函数访问;
6>静态数据成员主要用作类的所有对象公有的数据,如统计总数、平均数等。
二.静态成员函数
1.在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数属于整个类,是该类所有对象共享的成员函数,而不属于内种某个对象,定义静态成员函数的格式如下: static 返回类型 静态成员函数名(参数)
;
2.与静态数据成员类似,调用公有静态成员函数的一般格式有如下几种: 类名::静态成员函数名(实参)
对象.静态成员函数名(实参)
对象指针->静态成员函数名(实参)
下面是静态成员函数访问静态数据成员的例子:
#include<iostream>using namespace std;class Small_cat{ private: double weight; static double total_weight; static double total_number; public: Small_cat(double w); void display(); static void total_disp();};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(){ cout<<total_number<<"只小猫的总重量是:"; cout<<total_weight<<"千克"<<endl;}double Small_cat::total_weight=0;double Small_cat::total_number=0;int main(void){ Small_cat w1(0.5),w2(0.6),w3(0.4); w1.display(); w2.display(); w3.display(); Small_cat::total_disp(); return 0;}
运行结果如下:
这只小猫的重量是:0.5千克这只小猫的重量是:0.6千克这只小猫的重量是:0.4千克3只小猫的总重量是:1.5千克
【分析】上面的程序中声明了一个类Small_cat,在类中定义了两个静态数据成员total weight和total _number分别用来累计小猫的重量和累计小猫的只数;在类中还定义了一个静态成员函数total 用来显示小猫的只数和总重量。每当定义了一个类Small _cat的对象时,就通过调用构造函数把每只猫的的重量weight加到总重量total _weight上,同时对象计数器total _number加1,即累计小猫的只数。
3.说明
1>一般情况下,静态函数成员主要用来访问静态数据成员。当它与静态数据成员一起使用时,达到了对同一个类中对象之间共享数据的目的;
2>私有静态成员函数不能做类外部的函数和对象访问;
3>使用静态成员函数的一个原因是,可以用它在建立任何对象之前调用静态成员函数,以处理静态数据成员,这是普通成员函数不能实现的功能。例如:
int main(void){ Small_cat::total_disp();//可以用它在建立任何对象之前调用静态成员函数 Small_cat w1(0.5),w2(0.6),w3(0.4); . . .}
4>编译系统将静态成员函数限定为内部连接,也就是说,与现行文件相连接的其他文件中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性,这是使用静态成员函数的另一个原因;
5>静态成员函数是类的一部分,不是对象的一部分。如果要在类外调用公有
的静态成员函数,使用如下格式: 类名::静态成员函数名()
;
如上例中的Small_cat::total_disp();
当然如果已经定义了这个类的对象,就用对象引用函数的方法实现就可以;
6>静态成员函数与非静态成员函数的重要区别是:
非静态成员函数有this指针,而静态成员函数没有this指针;
静态成员函数可以直接访问本类中的静态数据成员,因为静态数据成员同样是属于类的,可以直接访问。一般而言,静态成员函数不访问类中的非静态成员,例如:
cout<<"一只小猫的重量是:"<<weight<<"千克\n";//不合法,weight是非静态数据成员cout<<"小猫的总重量是:"<<total_weight<<"千克"<<endl;//合法,total_weight是静态数据成员
若确实需要访问非静态数据成员,静态成员函数只能通过对象名(对象指针、对象引用)访问该对象的非静态成员。如把display函数定义为静态成员函数时,可将对象的引用作为函数参数,将它定义为:
static void display(small_cat &w){cout<<"这只小猫的重量是:"<<w.weight<<"千克\n";}
- C++学习笔记1——静态成员
- C++静态成员学习笔记
- .Net C#(类的静态成员/属性)——学习笔记
- 静态成员-学习笔记
- C#—静态成员和实例成员
- C++——静态成员
- Object-C学习——类的静态成员
- C/C++静态成员变量和静态成员函数(学习笔记)
- C++——static静态成员
- Objective-C学习笔记(十六)——成员变量
- C#——面向对象——静态成员和静态类——静态成员
- NDK开发学习笔记—C/C++访问java成员
- C++学习——静态成员
- 达内学习笔记——静态成员函数,匿名对象,
- JavaScript学习笔记(二十六) 静态成员
- C++学习笔记-静态成员注意事项
- C++笔记——类的静态成员和静态成员函数
- C++(学习笔记)——VS2015静态编译libcurl
- C++实验2-项目一
- 浪涌防护器件的应用
- 自定义一个图片shape
- ACM44 子串和(找到最大和)
- 编写高性能的Lua代码
- C++学习笔记1——静态成员
- Android 百分比布局库(percent-support-lib) 解析与扩展
- 实现activity变暗的效果
- Xcode7.2与iOS9之坑 (持续更新)
- BZOJ3223&3224 文艺&普通平衡树 Splay模板(数组)
- java 为什么使用工厂方法设计模式
- R 语言介绍
- HDU 5615:Jam's math problem【模拟】
- 键盘通知和自定义键盘