C++学习笔记1——静态成员
2016-03-22 17:33
555 查看
静态成员的提出是为了实现一个类的多个对象之间的数据共享。静态成员包括静态数据成员和静态函数成员。
一.静态数据成员
1.先举一个出现错误的代码来作为引例引出静态成员。
错误的输出结果为:
【分析】本例子的设计思想是,希望每定义一个对象,调用一次构造函数,使数据成员count加1从而累计学生人数,同时用数据成员sum累加学生成绩,求出学生的累加成绩,用数据成员ave计算平均成绩。但是这个例子的运行结果是错误的。其原因是,一个学生对象的count、sum和ave仅仅属于这个学生对象,而不是所有学生对象所共享的,因此它们不能表示所有学生的人数、累加成绩和平均成绩。为了使count、sum和ave被所有的对象共享,可以有两种解决方案。第一个方法是,将count、sum和ave说明为 全局变量。但是,使用全局变量会带来不安全性,并且破坏了面向对象程序设计的信息隐蔽技术,与面向对象的封装性特点是矛盾的。第二个方法就是使用
2.静态数据成员的定义如下:
将上例中count、sum和ave改为静态数据成员来处理,过程及结果如下:
正确运行结果:
3.说明:
1>静态数据成员的定义与普通数据成员相似,但前面要加上
2>静态数据成员的初始化与普通数据成员不同。静态数据成员初始化应在类外单独进行,而且应在定义对象之前进行,一般在主函数main之前,类声明之后的特殊地带为它提供定义和初始化。初始化的格式如下:
注意:这个时候在数据成员名前面不要加static
3>静态数据成员属于类(准确说是属于类对象的集合),而不像普通数据成员那样属于某一个对象,因此可以使用
4>静态数据成员和静态变量一样,是在编译时创建并初始化。它在该类的任何对象被建立之前就存在,因此,公有的静态数据成员可以在对象定义之前被访问(一般给静态数据成员初始化赋值的时候属于定义对象之前的访问),定义对象后,公有的静态数据成员也可以通过对象进行访问:
5>私有静态数据成员不能在类外直接访问,必须通过公有的成员函数函数访问;
6>静态数据成员主要用作类的所有对象公有的数据,如统计总数、平均数等。
二.静态成员函数
1.在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数属于整个类,是该类所有对象共享的成员函数,而不属于内种某个对象,定义静态成员函数的格式如下:
2.与静态数据成员类似,调用公有静态成员函数的一般格式有如下几种:
下面是静态成员函数访问静态数据成员的例子:
运行结果如下:
【分析】上面的程序中声明了一个类Small_cat,在类中定义了两个静态数据成员total weight和total _number分别用来累计小猫的重量和累计小猫的只数;在类中还定义了一个静态成员函数total 用来显示小猫的只数和总重量。每当定义了一个类Small _cat的对象时,就通过调用构造函数把每只猫的的重量weight加到总重量total _weight上,同时对象计数器total _number加1,即累计小猫的只数。
3.说明
1>一般情况下,静态函数成员主要用来访问静态数据成员。当它与静态数据成员一起使用时,达到了对同一个类中对象之间共享数据的目的;
2>私有静态成员函数不能做类外部的函数和对象访问;
3>使用静态成员函数的一个原因是,可以用它在建立任何对象之前调用静态成员函数,以处理静态数据成员,这是普通成员函数不能实现的功能。例如:
4>编译系统将静态成员函数限定为内部连接,也就是说,与现行文件相连接的其他文件中的同名函数不会与该函数发生冲突,维护了该函数使用的安全性,这是使用静态成员函数的另一个原因;
5>静态成员函数是类的一部分,不是对象的一部分。如果要在类外调用
如上例中的
当然如果已经定义了这个类的对象,就用对象引用函数的方法实现就可以;
6>静态成员函数与非静态成员函数的重要区别是:
非静态成员函数有this指针,而静态成员函数没有this指针;
静态成员函数可以直接访问本类中的静态数据成员,因为静态数据成员同样是属于类的,可以直接访问。一般而言,静态成员函数不访问类中的非静态成员,例如:
若确实需要访问非静态数据成员,静态成员函数只能通过对象名(对象指针、对象引用)访问该对象的非静态成员。如把display函数定义为静态成员函数时,可将对象的引用作为函数参数,将它定义为:
一.静态数据成员
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++实验2-项目一
- 简单的锁键盘锁鼠标的C++病毒代码
- [LeetCode] Reverse Words in a String II(in-place 算法)
- C++ Chapter 1. General(综述)
- [Lintcode]Reverse Words in a String
- 内存存储格式打印
- C++中类相关知识点总结
- 各种进制输入输出(c++)
- c语言学习之位运算知识总结和实例分析
- c/c++变量交换
- 深入理解C指针学习笔记(二)
- C++计算四则运算表达式程序
- gnuplot-cpp library使用记录
- c++ --> #define中的三个特殊符号:#,##,#@
- 关于Windows 开发遇到的字符转换问题
- C语言的time函数
- [蓝牙] 6、基于nRF51822的蓝牙心率计工程消息流Log分析(详细)
- [LeetCode294] Flip Game II
- VC++ 调用7z.exe 命令行参数实现简单的压缩、解压
- C++面试题30道