300 likes | 462 Views
静态成员. 引入 : 类是类型而不是数据对象,每个类的对象都是该类数据成员的拷贝,然而有时需要让类的所有对象在类的范围内共享某个数据,这些数据是类中所有对象所共有的。 声明为 static 类的成员能在类的范围内共享,称为:静态成员。. 静态成员有 : 静态数据和静态函数 。. 例如类: class student { char *name, *num; int total; // 学生总人数 public: …… }; 应用程序中声明对象为: student a, b, c;
E N D
静态成员 引入: 类是类型而不是数据对象,每个类的对象都是该类数据成员的拷贝,然而有时需要让类的所有对象在类的范围内共享某个数据,这些数据是类中所有对象所共有的。 声明为static类的成员能在类的范围内共享,称为:静态成员。 静态成员有: 静态数据和静态函数。
例如类: class student { char *name, *num; int total; //学生总人数 public: …… }; 应用程序中声明对象为: student a, b, c; 则对象a,b,c 中都有数据 total,而学生总数是一样的,所以total 被重复定义了两次。若把 total 声明为静态成员,就可避免这个问题。
定义形式 : 在所要定义的数据成员前加关键字 static, 如: class student { char *name; char *num; static int total; public: …… }; 将学生总人数 total 声明为静态成员
静态数据成员: • 若将一个数据成员说明为static,这个成员就是静态数据成员。 • 静态数据成员是静态的,必须对它进行初始化。 • 格式为: • 数据类型 类名::静态数据成员名=值; • 注意: • 初始化是在类体外进行的,在类中不为它分配内存空间。 • 初始化时不加访问权限控制符。 • 初始化时必须使用作用域运算符::来表明所属的类。
静态数据成员的访问: • 格式: • 类名::静态数据成员 • 静态成员应用场合: • 用来保存流动变化的对象的个数 • 作为一个标志 • 一个指向一个链表第一个成员或最后一个成员的指针。
例:静态数据成员的应用 #include <iostream.h> #include <string.h> class st_n { char *name, *num; //学生姓名、学号。 static int total; //学生总人数, 静态数据 public: }; st_n(char *, char *); ~st_n( ); void print( );
int st_n::total=0; //静态成员的初始化 st_n::st_n(char *n1, char *n2) { name=new char[strlen(n1)+1]; num =new char[strlen(n2)+1]; strcpy(name, n1); strcpy(num, n2); ++total; //学生人数加1 } void st_n::print( ) { cout << "\n name:" << name << "\n num: " << num << "\n total: " << total; } st_n::~st_n ( ) { delete [ ] name; delete [ ] num; - -total; //学生人数减1 }
void main( ) { st_n a("Wang ", "000001 "); st_n b("Yang ", "000002 "); st_n c(" Tang ", "000003 "); a.print( ); b.print( ); } 结果: name: Wang num: 000001 total: 3 name: Yang num: 000002 total: 3 注意:a, b, c 的 total 都是3,即说明静态成员只有一个, 且为所有对象共享。
静态函数成员 目的: 对静态数据成员进行访问修改。 形式: 在成员函数声明前加 static 调用: 类名::静态成员函数名(参 数表) • 注意点 • 只能访问静态数据, 不能访问其它成员。 • 可以没有对象而进行函数调用。
例:静态函数的应用(接前例) #include <iostream.h> #include <string.h> class st_n { char *name, *num; //学生姓名、学号。 static int total; //学生总人数, 静态成员 public: st_n(char *, char *); ~st_n( ); void print( ); static int getTotal( ); //静态函数 };
int st_n::total=0; //静态成员的初始化 st_n::st_n(char *n1, char *n2) { name=new char[strlen(n1)+1]; num =new char[strlen(n2)+1]; strcpy(name, n1); strcpy(num, n2); ++total; //学生人数加1 }
int st_n::getTotal( ) //定义静态函数 { return total; //只能访问静态函数 } void st_n::print( ) { cout << "name:" << name << endl; << "num: " << num << endl; } st_n::~st_n ( ) { delete [ ] name; delete [ ] num; - -total; //学生人数减1 }
void main( ) { st_n a("Wang ", "000001 "); st_n b("Yang ", "000002 "); st_n c(" Tang ", "000003 "); a.print( ); cout << " total: " << a.getTotal << endl; b.print( ); cout << " total: " << st_n::getTotal << endl; } 结果: name: Wang num: 000001 total: 3 name: Yang num: 000002 total: 3
友元 友元的引入: C++提供的一种有条件打破访问封装的机制,在不影响数据安全性的前提下,是类的”朋友“能够从类的外部访问类的私有成员 友元函数: 不是本类的成员函数,而是独立于本类的外部函数,本类允许友元函数通过对象名访问它的私有成员和保护成员。 友员函数: friend 函数原型声明; 友员类: 一个类作为另外一个类的友元 friend class 友员类名;
例 . 友员函数 #include <iostream.h> #include <string.h> class st_n { public: }; char *name, *num; //学生姓名、学号。 friend void show( st_n &st) { cout << "\n name:" << st.name << "\n num: " << st.num; } st_n(char *n1, char *n2) { name=new char[strlen(n1)+1]; num =new char[strlen(n2)+1]; strcpy(name, n1); strcpy(num, n2); }
class sco { public: int mat, eng; //学生数学、英语成绩。 friend void show_all(st_n &, sco *); sco(int i1, int i2) :mat(i1),eng(i2) { } }; //外部函数 void show_all(st_n &st, sco *p ) { show(st); cout << "\n mathematics:" << p->mat << "\n english: " << p->eng; }
void main( ) { st_n a("Wang ", "123456 "); //创建对象 sco b(72, 82); //创建对象 b.show_all(a, &b); //打印姓名、学号 //数学、英语成绩 } 结果: name: Wang num: 12345 mathematics:72 english: 82 注意:定义了两个类 a,b,且外部友员函数show_all 能访问私有数据,建立了类与外部函数之间的联系。
例题:友元类 #include <iostream.h> #include <string.h> class st_n { public: }; friend class sco; //定义友员类 char *name, *num; //学生姓名、学号。 st_n(char *n1, char *n2) { name=new char[strlen(n1)+1]; num =new char[strlen(n2)+1]; strcpy(name, n1); strcpy(num, n2); } //没有函数dsp( )
class sco { public: }; int mat, eng; //学生数学、英语成绩。 sco(int i1, int i2) :mat(i1),eng(i2) { } void show( ) { cout << "\n mathematics:" << mat << "\n english: " << eng; } void show( st_n &st) { cout << "\n name:" << st.name << "\n num: " << st.num; }
void main( ) { st_n a("Wang ", "123456 "); //创建对象 sco b(72, 82); //创建对象 b.show(a); //打印姓名、学号 b.show( ); //打印数学、英语成绩 } 结果: name: Wang num: 12345 mathematics:72 english: 82 注意:定义了两个类 a,b,但b能访问私有数据,建立了类之间的联系。
总结 1. 定义了类sco 是类 st_n 的友员,建立了 类之间的联系。使编程显得更便利。 2. 友员可以访问并修改类的私有和保护数 据,调用类的私有和保护函数,使类不 至于由于封装而增加了编程的复杂性。 总的目标:使外部类能访问修改类的私有或保护数据、能调用类的私有或保护函数。
友员成员函数:除了一般的函数可以作为某个类的友元外,友员成员函数:除了一般的函数可以作为某个类的友元外, 一个类的成员函数也可以作为另外一个类的友元。 例 :友元成员函数 #include <iostream.h> #include <string.h> class st_n; //仅为原型定义,具体实现在后面 class sco { public: }; int mat, eng; //学生数学、英语成绩。 sco(int i1, int i2) :mat(i1),eng(i2) { } void show( ) { cout << "\n mathematics:" << mat << "\n english: " << eng; } void show( st_n &st);
class st_n { public: }; friend void sco::show(st_n &); //定义友员 char *name, *num; //学生姓名、学号。 st_n(char *n1, char *n2) { name=new char[strlen(n1)+1]; num =new char[strlen(n2)+1]; strcpy(name, n1); strcpy(num, n2); } void sco::show( st_n &st) { cout << "\n name:" << st.name << "\n num: " << st.num; show( ); }
void main( ) { st_n a("Wang ", "123456 "); //创建对象 sco b(72, 82); //创建对象 b.show(a); //打印姓名、学号、成绩 } 结果: name: Wang num: 12345 mathematics:72 english: 82 注意:定义了两个类 a,b,且b的成员函数show 能访问私有数据,建立了类与类成员函数之间的联系。
总结: 1. 定义了类sco 中的函数 show 是类 st_n 的友员,建立了类和类成员函数之间的 联系。使编程显得更便利。 2. 友员成员函数可以访问并修改类的私有 或保护数据,调用类的私有或保护函数 使类不至于由于封装而增加了编程的复 杂性。 总的目标:使外部类的成员函数能访问修改类的私有或保护数据、能调用类的私有或保护函数。与友员类的区别是仅将部分成员函数声明为友员, 而不是整个类.
几点注意 1. 友员关系不能传递: 即你是我的朋友, 他 是你的朋友, 但不一定他是我的朋友.从 另一个角度说, 我愿意和你分享我的秘 密, 但不一定愿意和你的朋友分享我的秘 密. 2. 友员关系不是可逆的, 即: 甲是乙的友员, 并不意味着乙是甲的友员. 从另一个角 度说, 我愿意和你分享我的秘密, 但不一 定你愿意和我分享你的秘密
课 堂 总 结 1 、 友员有三种形式:友员类、友员成员函数和 友员函数。 2 、友员可以访问并修改类的私有或保护数据, 调用类的私有或保护成员函数,使类既具 有封装性,又具有灵活性。 3 、 友员关系不能传递,不是互逆的。
const对象 可以在类中使用const关键字定义成员函数,也可以修饰一个对象,这时一个const对象只能访问const成员函数,否则将产生编译错误。 const可以放在成员函数的前面,也可以放在成员函数的后面。 1)放在成员函数的前面 表示函数的返回值为一个常量对象。 2)放在成员函数的后面 表示函数不能对数据成员进行修改
void main() { ConstFun s; const int i=s.f5(); int y=Obj(); cout<<i<<“ “<<y<<endl; const ConstFun d; int j=d.f5(); cout<<d<<endl; } 例题: #include<iostream.h> class ConstFun { public: const int f5() const { return 5; } int Obj() { return 45; }
例题: #include<iostream.h> class ConstFun { int value; public: int GetValue() const; int ReadValue() const { return value;}}; ConstFun::GetValue() const{ return value;} void main() { ConstFun s(98); cout<<s.GetValue()<<endl; } 提示:一定要确保在正确的位置使用const,而且在函数定义时也必须重复使用const。否则,编译器会给出错误提示。