资源预览内容
第1页 / 共111页
第2页 / 共111页
第3页 / 共111页
第4页 / 共111页
第5页 / 共111页
第6页 / 共111页
第7页 / 共111页
第8页 / 共111页
第9页 / 共111页
第10页 / 共111页
亲,该文档总共111页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006 多态性(PolymorphismPolymorphism)是指一个名字,多种语义;或界面 相同,多种实现。 重载函数是多态性的一种简单形式。 虚函数允许函数调用与函数体的联系在运行时才进行,称为 动态联编。第第8 8章章 虚函数与多态性虚函数与多态性华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006第第8 8章章 虚函数与多态性虚函数与多态性华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006联编是指一个程序模块、代码之间互相关联的过程。静态联编,是程序的匹配、连接在编译阶段实现,也称为早期匹配。重载函数使用静态联编。动态联编是指程序联编推迟到运行时进行,所以又称为晚期联编。switch语句和if语句是动态联编的例子。8.1 8.1 8.1 8.1 静态联编静态联编静态联编静态联编华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.1 8.1 8.1 8.1 静态联编静态联编静态联编静态联编普通成员函数重载可表达为两种形式:1.在一个类说明中重载例如:voidShow(int,char);voidShow(char*,float);华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.1 8.1 8.1 8.1 静态联编静态联编静态联编静态联编普通成员函数重载可表达为两种形式:1.在一个类说明中重载例如:voidShow(int,char);与voidShow(char*,float);不是同一函数,编译能够区分2.基类的成员函数在派生类重载。有3种编译区分方法:(1)根据参数的特征加以区分华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.1 8.1 8.1 8.1 静态联编静态联编静态联编静态联编普通成员函数重载可表达为两种形式:1.在一个类说明中重载2.基类的成员函数在派生类重载。有3种编译区分方法:(1)根据参数的特征加以区分例如:A:Show();有别于B:Show();(2)使用“:”加以区分华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.1 8.1 8.1 8.1 静态联编静态联编静态联编静态联编普通成员函数重载可表达为两种形式:1.在一个类说明中重载2.基类的成员函数在派生类重载。有3种编译区分方法:(1)根据参数的特征加以区分(2)使用“:”加以区分例如:Aobj.Show()调用A:Show()Bobj.Show()调用B:Show()(3)根据类对象加以区分根据根据this指针类型区分指针类型区分华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006基类指针和派生类指针与基类对象和派生类对象4种可能匹配:直接用基类指针引用基类对象;直接用派生类指针引用派生类对象;用基类指针引用一个派生类对象;用派生类指针引用一个基类对象。8.2 8.2 8.2 8.2 类指针的关系类指针的关系类指针的关系类指针的关系8.2类指针的关系华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006例如:例如:A*p;/ 指向类型指向类型 A 的对象的指针的对象的指针AA_obj;/ 类型类型 A 的对象的对象BB_obj;/ 类型类型 B 的对象的对象p=&A_obj;/ p 指向类型指向类型 A 的对象的对象p=&B_obj;/ p 指向类型指向类型 B 的对象,它是的对象,它是 A 的派生类的派生类利用p,可以通过B_obj访问所有从A类继承的元素,但不能用p访问B类自定义的元素(除非用了显式类型转换)classAclassB:publicA8.2.1 8.2.1 基类指针引用派生类对象基类指针引用派生类对象8.2.1基类指针引用派生类对象华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 classA_classclassB_class:publicA_class8.2.1基类指针引用派生类对象华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();基类指针基类指针classA_classclassB_class:publicA_class8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();基类指针基类指针指向基类对象指向基类对象classA_classclassB_class:publicA_class8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();基类指针基类指针调用基类成员函数调用基类成员函数classA_classclassB_class:publicA_class8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();classA_classclassB_class:publicA_class基类指针基类指针指向派生类对象指向派生类对象8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();classA_classclassB_class:publicA_class调用调用从基类继承的成员函数从基类继承的成员函数8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();classA_classclassB_class:publicA_class用派生类对象用派生类对象调用派生类的成员函数调用派生类的成员函数8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();classA_classclassB_class:publicA_class对基类指针强类型转换对基类指针强类型转换调用派生类的成员函数调用派生类的成员函数8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassA_classcharname20;public:voidput_name(char*s)strcpy(name,s);voidshow_name()coutnamen;classB_class:publicA_classcharphone_num20;public:voidput_phone(char*num)strcpy(phone_num,num);voidshow_phone()coutphone_numput_name(Wangxiaohua);A_p-show_name();A_p=&B_obj;A_p-put_name(Chenming);A_p-show_name();B_obj.put_phone(5555_12345678);(B_class*)A_p)-show_phone();classA_classclassB_class:publicA_class8.2.1基类指针引用派生类对象例例8-1 8-1 使用基类指针引用派生类对象使用基类指针引用派生类对象 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006派生类指针只有经过强制类型转换之后,才能引用基类对象8.2.2 8.2.2 派生类指针引用基类对象派生类指针引用基类对象 8.2.2派生类指针引用基类对象华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassDatepublic:Date(inty,intm,intd)SetDate(y,m,d);voidSetDate(inty,intm,intd)year=y;month=m;day=d;voidPrint()coutyear/month/dayPrint();couthours:minutes:secondsn;private:inthours,minutes,seconds;voidmain()DateTimedt(2003,1,1,12,30,0);dt.Print();例例8-2 日期时间程序。在派生类中调用基类日期时间程序。在派生类中调用基类同名成员函数同名成员函数 8.2.2派生类指针引用基类对象华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassDatepublic:Date(inty,intm,intd)SetDate(y,m,d);voidSetDate(inty,intm,intd)year=y;month=m;day=d;voidPrint()coutyear/month/dayPrint();couthours:minutes:secondsPrint();对对 this指针作类型转换指针作类型转换调用基类成员函数调用基类成员函数8.2.2派生类指针引用基类对象例例8-2 日期时间程序。在派生类中调用基类日期时间程序。在派生类中调用基类同名成员函数同名成员函数 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassDatepublic:Date(inty,intm,intd)SetDate(y,m,d);voidSetDate(inty,intm,intd)year=y;month=m;day=d;voidPrint()coutyear/month/dayPrint();couthours:minutes:secondsPrint();对对 this指针作类型转换指针作类型转换调用基类成员函数调用基类成员函数8.2.2派生类指针引用基类对象例例8-2 日期时间程序。在派生类中调用基类日期时间程序。在派生类中调用基类同名成员函数同名成员函数 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#include#includeclassDatepublic:Date(inty,intm,intd)SetDate(y,m,d);voidSetDate(inty,intm,intd)year=y;month=m;day=d;voidPrint()coutyear/month/dayPrint();(Date*)this)-Print();couthours:minutes:secondsn;private:inthours,minutes,seconds;voidmain()DateTimedt(2003,1,1,12,30,0);dt.Print();8.2.2派生类指针引用基类对象例例8-2 日期时间程序。在派生类中调用基类日期时间程序。在派生类中调用基类同名成员函数同名成员函数 Date:Print();Date:Print();等价吗?等价吗?等价吗?等价吗? 为什么?为什么?为什么?为什么?华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006冠以关键字virtual的成员函数称为虚函数 实现运行时多态的关键首先是要说明虚函数,另外,必须用 基类指针调用派生类的不同实现版本8.3 8.3 8.3 8.3 虚函数和动态联编虚函数和动态联编虚函数和动态联编虚函数和动态联编 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006 基类指针虽然获取派生类对象地址,却只能访问派生类从基类继承的成员8.3.1 8.3.1 虚函数和基类指针虚函数和基类指针8.3.1 虚函数和基类指针华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();例例8-3 8-3 演示基类指针的移动演示基类指针的移动 8.3.1 虚函数和基类指针华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_obj8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objp定义基类指针定义基类指针8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();A ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();AT TOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();AT TOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOE ENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objpvoidwho()coutFirstderivedclass:x,yn;8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();AT TO OENDxyzB_objF_objS_objpvoidwho()coutFirstderivedclass:x,yn;通过对象调用成员函数通过对象调用成员函数8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objpvoidwho()coutSecondderivedclass:x,y,zn;8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOE EN ND DxyzB_objF_objS_objpvoidwho()coutSecondderivedclass:x,y,zn;基类指针做类型转换基类指针做类型转换8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();A AT TOE ENDxyzB_objF_objS_objp通过基类指针通过基类指针只能访问从基类继承的成员只能访问从基类继承的成员 8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;voidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();F_obj.who();(Second_d*)p)-who();ATOENDxyzB_objF_objS_objp修改程序修改程序修改程序修改程序定义虚函数定义虚函数定义虚函数定义虚函数8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtualvoidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;voidwho()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;voidwho()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();基类定义虚函数基类定义虚函数8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtualvoidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();派生类的重定义版本派生类的重定义版本默认为虚函数默认为虚函数8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_obj8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtualvoidwho()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();A ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_objpvoidwho()coutFirstderivedclass:x,yn;8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();AT TO OENDxyzB_objF_objS_objvoidwho()coutFirstderivedclass:x,yn;p8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_objp8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOENDxyzB_objF_objS_objvoidwho()coutSecondderivedclass:x,y,zn;p8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOE EN ND DxyzB_objF_objS_objvoidwho()coutSecondderivedclass:x,y,zn;p8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassBasepublic:Base(charxx)x=xx;virtual void who()coutBaseclass:xn;protected:charxcharx;classFirst_d:publicBasepublic:First_d(charxx,charyy):Base(xx)y=yy;void who()coutFirstderivedclass:x,yn;protected:charychary;classSecond_d:publicFirst_dpublic:Second_d(charxx,charyy,charzz):First_d(xx,yy)z=zz;void who()coutSecondderivedclass:x,y,zwho();p=&F_obj;p-who();p=&S_obj;p-who();ATOE EN ND DxyzB_objF_objS_objp由于由于由于由于who()who()who()who()的虚特性的虚特性的虚特性的虚特性随着随着随着随着p p p p指向不同对象,指向不同对象,指向不同对象,指向不同对象,thisthisthisthis指针作类型转换指针作类型转换指针作类型转换指针作类型转换执行不同实现版本执行不同实现版本执行不同实现版本执行不同实现版本 8.3.1 虚函数和基类指针例例8-3 8-3 演示基类指针的移动演示基类指针的移动 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006注意:一个虚函数,在派生类层界面相同的重载函数都保持虚特性虚函数必须是类的成员函数不能将友员说明为虚函数,但虚函数可以是另一个类的友员析构函数可以是虚函数,但构造函数不能是虚函数8.3.1 8.3.1 虚函数和基类指针虚函数和基类指针8.3.1 虚函数和基类指针华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006在派生类中重载基类的虚函数要求函数名、返回类型、参数个数、参数类型和顺序完全相同如果仅仅返回类型不同,C+认为是错误重载如果函数原型不同,仅函数名相同,丢失虚特性8.3.2 8.3.2 虚函数的重载特性虚函数的重载特性8.3.2 虚函数的重载特性华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006例:例:classbasepublic:virtualvoidvf1();virtualvoidvf2();virtualvoidvf3();voidf();voidg()derivedd;base*bp=&d;/ 基类指针指向派生类对象基类指针指向派生类对象bp-vf1();/ 调用调用 deriver : vf1 ( )bp-vf2();/ 调用调用 base : vf2 ( )bp-f();/ 调用调用 base : f ( );classderived:publicbasepublic:voidvf1();/ 虚函数虚函数voidvf2(int);/ 重载,参数不同,虚特性丢失重载,参数不同,虚特性丢失char vf3 ( );/ error,仅返回类型不同,仅返回类型不同voidf();/ 非虚函数重载非虚函数重载;8.3.2 8.3.2 虚函数的重载特性虚函数的重载特性8.3.2 虚函数的重载特性华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006构造函数不能是虚函数。建立一个派生类对象时,必须从类层次的根开始,沿着继承路径逐个调用基类的构造函数析构函数可以是虚的。虚析构函数用于指引delete运算符正确析构动态对象8.3.3 8.3.3 虚析构函数虚析构函数8.3.3 虚析构函数华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;例例8-4 普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况8.3.3 虚析构函数华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;用基类指针用基类指针建立派生类的动态对象建立派生类的动态对象8.3.3 虚析构函数例例8-4 普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;用用派生类派生类指针指针建立派生类的动态对象建立派生类的动态对象8.3.3 虚析构函数例例8-4 普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A *Ap = new B ;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;析构由基类指针建立的派生类对象析构由基类指针建立的派生类对象没有调用派生类析构函数没有调用派生类析构函数8.3.3 虚析构函数例例8-4 普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B *Bp2 = new B ;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;析构由派生类指针建立的派生类对象析构由派生类指针建立的派生类对象正确调用派生类析构函数正确调用派生类析构函数8.3.3 虚析构函数例例8-4 普通析构函数在删除动态派生类对象的调用情况普通析构函数在删除动态派生类对象的调用情况华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;例例8-5 虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况virtualA()coutA:A()iscalled.n;8.3.3 虚析构函数华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A *Ap = new B ;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;例例8-5 虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况virtualA()coutA:A()iscalled.n;正确调用派生类构造函数正确调用派生类构造函数释放所有资源释放所有资源8.3.3 虚析构函数华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassApublic:A()coutA:A()iscalled.n;classB:publicApublic:B()coutB:B()iscalled.n;voidmain()A*Ap=newB;B*Bp2=newB;coutdeletefirstobject:n;deleteAp;coutdeletesecondobject:n;deleteBp2;例例8-5 虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况虚析构函数在删除动态派生类对象的调用情况virtualA()coutA:A()iscalled.n;8.3.3 虚析构函数华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.4 8.4 8.4 8.4 纯虚函数和抽象类纯虚函数和抽象类纯虚函数和抽象类纯虚函数和抽象类纯虚函数是一个在基类中说明的虚函数,在基类中没有定义, 要求任何派生类都定义自己的版本纯虚函数为各派生类提供一个公共界面纯虚函数说明形式: virtual 类型 函数名(参数表)= 0= 0 ; ; 一个具有纯虚函数的基类称为抽象类。 8.4 纯虚函数和抽象类华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006classpoint/*/;classshape;/ 抽象类抽象类pointcenter;public:pointwhere()returncenter;voidmove(pointp)enter=p;draw();virtualvoidrotate(int)=0;/ 纯虚函数纯虚函数virtualvoiddraw()=0;/ 纯虚函数纯虚函数;.shape x ;/ error,抽象类不能建立对象,抽象类不能建立对象shape*p;/ ok,可以声明抽象类的指针,可以声明抽象类的指针shape f ( ) ;/ error, 抽象类不能作为函数返回类型抽象类不能作为函数返回类型void g ( shape ) ;/ error, 抽象类不能作为参数类型抽象类不能作为参数类型shape&h(shape&);/ ok,可以声明抽象类的引用,可以声明抽象类的引用例如:例如:8.4 纯虚函数和抽象类华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006classpoint/*/;classshape;/ 抽象类pointcenter;public:pointwhere()returncenter;voidmove(pointp)enter=p;draw();virtualvoidrotate(int)=0;/ 纯虚函数virtualvoiddraw()=0;/ 纯虚函数;.classab_circle:publicshapeintradius;public:voidrotate(int);例如:例如:ab_circle类仍为抽象类类仍为抽象类ab_circle:draw()、ab_circle:rotate()也是纯虚函数也是纯虚函数8.4 纯虚函数和抽象类要使ab_circle成为非抽象类,必须作以下说明:classab_circle:publicshapeintradius;public:voidrotate(int);voiddraw();并提供ab_circle:draw()和ab_circle:rotate(int)的定义华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/figure.hclassfigureprotected:doublex,y;public:voidset_dim(doublei,doublej=0)x=i;y=j;virtualvoidshow_area()=0;classtriangle:publicfigurepublic:voidshow_area()coutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;classsquare:publicfigurepublic:voidshow_area()coutSquarewithdimensionx*yhasanareaofx*yn;classcircle:publicfigurepublic:voidshow_area()coutCirclewithradiusx;couthasanareaof3.14*x*xn;virtualvoidshow_area()=0;/纯虚函数纯虚函数例例8-6 8-6 简单图形类简单图形类 voidshow_area()voidshow_area()coutTrianglewithhighxandbaseyhasanareaofcoutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;x*0.5*yn;voidshow_area()voidshow_area()coutSquarewithdimensionx*yhasanareaofcoutSquarewithdimensionx*yhasanareaofx*yn;x*yn;voidshow_area()voidshow_area()coutCirclewithradiusx;coutCirclewithradiusx;couthasanareaof3.14*x*xn;couthasanareaof3.14*x*xn;8.4 纯虚函数和抽象类华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/figure.hclassfigureprotected:doublex,y;public:voidset_dim(doublei,doublej=0)x=i;y=j;virtualvoidshow_area()=0;classtriangle:publicfigurepublic:voidshow_area()coutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;classsquare:publicfigurepublic:voidshow_area()coutSquarewithdimensionx*yhasanareaofx*yn;classcircle:publicfigurepublic:voidshow_area()coutCirclewithradiusx;couthasanareaof3.14*x*xn;virtualvoidshow_area()=0;/纯虚函数纯虚函数voidshow_area()voidshow_area()coutTrianglewithhighxandbaseyhasanareaofcoutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;x*0.5*yn;voidshow_area()voidshow_area()coutSquarewithdimensionx*yhasanareaofcoutSquarewithdimensionx*yhasanareaofx*yn;x*yn;voidshow_area()voidshow_area()coutCirclewithradiusx;coutCirclewithradiusx;couthasanareaof3.14*x*xn;couthasanareaof3.14*x*xn;#include#includefigure.hvoidmain()trianglet;/派生类对象派生类对象squares;circlec;t.set_dim(10.0,5.0);t.show_area();s.set_dim(10.0,5.0);s.show_area();c.set_dim(9.0);c.show_area();8.4 纯虚函数和抽象类例例8-6 8-6 简单图形类简单图形类 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006例例8-6 8-6 简单图形类简单图形类 8.4 纯虚函数和抽象类/figure.hclassfigureprotected:doublex,y;public:voidset_dim(doublei,doublej=0)x=i;y=j;virtualvoidshow_area()=0;classtriangle:publicfigurepublic:voidshow_area()coutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;classsquare:publicfigurepublic:voidshow_area()coutSquarewithdimensionx*yhasanareaofx*yn;classcircle:publicfigurepublic:voidshow_area()coutCirclewithradiusx;couthasanareaof3.14*x*xn;virtualvoidshow_area()=0;/纯虚函数纯虚函数voidshow_area()voidshow_area()coutTrianglewithhighxandbaseyhasanareaofcoutTrianglewithhighxandbaseyhasanareaofx*0.5*yn;x*0.5*yn;voidshow_area()voidshow_area()coutSquarewithdimensionx*yhasanareaofcoutSquarewithdimensionx*yhasanareaofx*yn;x*yn;voidshow_area()voidshow_area()coutCirclewithradiusx;coutCirclewithradiusx;couthasanareaof3.14*x*xn;couthasanareaof3.14*x*xn;#include#includefigure.hvoidmain()figure*p;/ 声明抽象类指针声明抽象类指针trianglet;squares;circlec;p=&t;p-set_dim(10.0,5.0);/ triangle:set_dim()p-show_area();p=&s;p-set_dim(10.0,5.0);/ square:set_dim()p-show_area();p=&c;p-set_dim(9.0);/ circle:set_dim()p-show_area();华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;例例8-7 8-7 使用抽象类引用使用抽象类引用 voidfun(Number&n)/ 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Show()8.4 纯虚函数和抽象类华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;voidfun(Number&n)/ 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Show()抽象类引用抽象类引用8.4 纯虚函数和抽象类例例8-7 8-7 使用抽象类引用使用抽象类引用 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;voidfun(Number&n)/ 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Show()函数调用函数调用派生类对象派生类对象8.4 纯虚函数和抽象类例例8-7 8-7 使用抽象类引用使用抽象类引用 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;voidfun(Number&n)/ 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Show()8.4 纯虚函数和抽象类例例8-7 8-7 使用抽象类引用使用抽象类引用 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalendl;voidfun(Number&n)/ 抽象类的引用参数抽象类的引用参数n.Show();voidmain()Dec_typen1(50);fun(n1);/ Dec_type:Show()Hex_typen2(50);fun(n2);/ Hex_type:Show()Oct_typen3(50);fun(n3);/ Oct_type:Show()8.4 纯虚函数和抽象类例例8-7 8-7 使用抽象类引用使用抽象类引用 华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006#includeclassNumberpublic:Number(inti)val=i;virtualvoidShow()=0;protected:intval;classHex_type:publicNumberpublic:Hex_type(inti):Number(i)voidShow()coutHexadecimal:hexvalendl;classDec_type:publicNumberpublic:Dec_type(inti):Number(i)voidShow()coutDecimal:decvalendl;classOct_type:publicNumberpublic:Oct_type(inti):Number(i)voidShow()coutOctal:octvalShow();fun(&n1);fun(&n2);华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006 虚函数和多态性使成员函数根据调用对象的类型产生不同的动作 多态性特别适合于实现分层结构的软件系统,便于对问题抽象时 定义共性,实现时定义区别8.5 8.5 8.5 8.5 虚函数与多态的应用虚函数与多态的应用虚函数与多态的应用虚函数与多态的应用8.5 虚函数与多态的应用华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 200620068.5.1 8.5.1 一个实例一个实例 计算雇员工资计算雇员工资EmployeeHourWorkerManagerPieceWorker抽象类抽象类提供一般属性,共同操作界面提供一般属性,共同操作界面管理人员类管理人员类提供特殊属性,操作实现提供特殊属性,操作实现计时工人类计时工人类提供特殊属性,操作实现提供特殊属性,操作实现计件工人类计件工人类提供特殊属性,操作实现提供特殊属性,操作实现8.5.1 一个实例华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;protected:longnumber;/ 编号编号char*name;/ 姓名姓名;EmployeeEmployeeHourWorkerManagerPieceWorker8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;protected:longnumber;/ 编号编号char*name;/ 姓名姓名;EmployeeEmployeeHourWorkerManagerPieceWorker/虚析构函数虚析构函数8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;protected:longnumber;/ 编号编号char*name;/ 姓名姓名;EmployeeEmployeeHourWorkerManagerPieceWorker/虚析构函数虚析构函数/纯虚函数,计算月薪纯虚函数,计算月薪8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;protected:longnumber;/ 编号编号char*name;/ 姓名姓名;EmployeeEmployeeHourWorkerManagerPieceWorker/虚析构函数虚析构函数/纯虚函数,计算月薪纯虚函数,计算月薪/虚函数,输出编号、姓名虚函数,输出编号、姓名8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Manager.hclassManager:publicEmployeepublic:Manager(constlong,constchar*,double=0.0);Manager()voidsetMonthlySalary(double);virtualdoubleearnings()const;virtualvoidprint()const;private:doublemonthlySalary;EmployeeHourWorkerManagerManagerPieceWorker8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Manager.hclassManager:publicEmployeepublic:Manager(constlong,constchar*,double=0.0);Manager()voidsetMonthlySalary(double);virtualdoubleearnings()const;virtualvoidprint()const;private:doublemonthlySalary;EmployeeHourWorkerManagerManagerPieceWorker/私有数据,月薪私有数据,月薪8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Manager.hclassManager:publicEmployeepublic:Manager(constlong,constchar*,double=0.0);Manager()voidsetMonthlySalary(double);virtualdoubleearnings()const;virtualvoidprint()const;private:doublemonthlySalary;EmployeeHourWorkerManagerManagerPieceWorker/ 置月薪置月薪/私有数据,月薪私有数据,月薪8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Manager.hclassManager:publicEmployeepublic:Manager(constlong,constchar*,double=0.0);Manager()voidsetMonthlySalary(double); virtualdoubleearnings()const;virtualvoidprint()const;private:doublemonthlySalary;EmployeeHourWorkerManagerManagerPieceWorker/ 置月薪置月薪/ 计算管理人员月薪计算管理人员月薪/私有数据,月薪私有数据,月薪8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Manager.hclassManager:publicEmployeepublic:Manager(constlong,constchar*,double=0.0);Manager()voidsetMonthlySalary(double);virtualdoubleearnings()const;virtualvoidprint()const;private:doublemonthlySalary;EmployeeHourWorkerManagerManagerPieceWorker/ 置月薪置月薪/ 计算管理人员月薪计算管理人员月薪/ 输出管理人员信息输出管理人员信息/私有数据,月薪私有数据,月薪8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerHourWorkerManagerPieceWorker/HourlyWorker.hclassHourlyWorker:publicEmployeepublic:HourlyWorker(constlong,constchar*,double=0.0,int=0);HourlyWorker()voidsetWage(double);voidsetHours(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewage;doublehours;8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerHourWorkerManagerPieceWorker/HourlyWorker.hclassHourlyWorker:publicEmployeepublic:HourlyWorker(constlong,constchar*,double=0.0,int=0);HourlyWorker()voidsetWage(double);voidsetHours(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewage;doublehours;/ 时薪时薪/ 工时工时8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerHourWorkerManagerPieceWorker/HourlyWorker.hclassHourlyWorker:publicEmployeepublic:HourlyWorker(constlong,constchar*,double=0.0,int=0);HourlyWorker()voidsetWage(double);voidsetHours(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewage;doublehours;/ 时薪时薪/ 工时工时/ 置时薪置时薪/ 置工时置工时8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerHourWorkerManagerPieceWorker/HourlyWorker.hclassHourlyWorker:publicEmployeepublic:HourlyWorker(constlong,constchar*,double=0.0,int=0);HourlyWorker()voidsetWage(double);voidsetHours(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewage;doublehours;/ 置时薪置时薪/ 置工时置工时/ 输出计时工月薪输出计时工月薪/ 计算计时工月薪计算计时工月薪/ 时薪时薪/ 工时工时8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerManagerPieceWorkerPieceWorker/PieceWorker.hclassPieceWorker:publicEmployeepublic:PieceWorker(constlong,constchar*,double=0.0,int=0);PieceWorker()voidsetWage(double);voidsetQuantity(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewagePerPiece;intquantity;8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerManagerPieceWorkerPieceWorker/PieceWorker.hclassPieceWorker:publicEmployeepublic:PieceWorker(constlong,constchar*,double=0.0,int=0);PieceWorker()voidsetWage(double);voidsetQuantity(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewagePerPiece;intquantity;/ 每件工件薪金每件工件薪金/ 工件数工件数8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerManagerPieceWorkerPieceWorker/PieceWorker.hclassPieceWorker:publicEmployeepublic:PieceWorker(constlong,constchar*,double=0.0,int=0);PieceWorker()voidsetWage(double);voidsetQuantity(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewagePerPiece;intquantity;/ 置每件工件薪金置每件工件薪金/ 置工件数置工件数/ 每件工件薪金每件工件薪金/ 工件数工件数8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerManagerPieceWorkerPieceWorker/PieceWorker.hclassPieceWorker:publicEmployeepublic:PieceWorker(constlong,constchar*,double=0.0,int=0);PieceWorker()voidsetWage(double);voidsetQuantity(int);virtualdoubleearnings()const;virtualvoidprint()const;private:doublewagePerPiece;intquantity;/ 置每件工件薪金置每件工件薪金/ 置工件数置工件数/ 每件工件薪金每件工件薪金/ 工件数工件数/ 输出计件薪金输出计件薪金/ 计算计件薪金计算计件薪金8.5.1 一个实例例例8-8 8-8 计算雇员工资计算雇员工资华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006EmployeeHourWorkerManagerPieceWorker8.5.1 一个实例voidtest1()coutsetiosflags(ios:fixed|ios:showpoint)print();basePtr=&m2;basePtr-print();basePtr=&hw1;basePtr-print();basePtr=&hw2;basePtr-print();basePtr=&pw1;basePtr-print();basePtr=&pw2;basePtr-print();调用函数语句调用函数语句形式相同形式相同华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006 程序中,用基类类型指针,可以生成一个连接不同派生类对象的 动态链表,即每个结点指针可以指向类层次中不同的派生类对象。 这种结点类型不相同链表称为异质链表。8.5.2 8.5.2 异质链表异质链表8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;Employee*next;protected:longnumber;char*name;EmployeeHourWorkerManagerPieceWorker8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006/Employee.hclassEmployeepublic:Employee(constlong,constchar*);virtualEmployee();constchar*getName()const;constlonggetNumber()const;virtualdoubleearnings()const=0;virtualvoidprint()const;Employee*next;Employee*next;protected:longnumber;char*name;EmployeeHourWorkerManagerPieceWorker/ 增加一个指针成员增加一个指针成员8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006voidAddFront(Employee*&h,Employee*&t)/ 在表头插入结点在表头插入结点t-next=h;h=t;voidtest3()/ 测试函数测试函数Employee*empHead=NULL,*ptr;ptr=newManager(10135,ChengShaoHua,1200);/ 建立第一个结点建立第一个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newHourlyWorker(30712,ZhaoXiaoMing,5,8*20);/ 建立第二个结点建立第二个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newPieceWorker(20382,XiuLiWei,0.5,2850);/ 建立第三个结点建立第三个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=empHead;while(ptr)ptr-print();ptr=ptr-next;/ 遍历链表,输出全部信息遍历链表,输出全部信息ptr=empHead;while(ptr)/ 遍历链表,输出姓名和工资遍历链表,输出姓名和工资coutgetName()earnings()next;8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006voidAddFront(Employee*&h,Employee*&t)/ 在表头插入结点在表头插入结点t-next=h;h=t;voidtest3()/ 测试函数测试函数Employee*empHead=NULL,*ptr;ptr=newManager(10135,ChengShaoHua,1200);/ 建立第一个结点建立第一个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newHourlyWorker(30712,ZhaoXiaoMing,5,8*20);/ 建立第二个结点建立第二个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newPieceWorker(20382,XiuLiWei,0.5,2850);/ 建立第三个结点建立第三个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=empHead;while(ptr)ptr-print();ptr=ptr-next;/ 遍历链表,输出全部信息遍历链表,输出全部信息ptr=empHead;while(ptr)/ 遍历链表,输出姓名和工资遍历链表,输出姓名和工资coutgetName()earnings()next;ptr=newptr=new ManagerManager(10135,ChengShaoHua,1200);(10135,ChengShaoHua,1200);ptr=newptr=new HourlyWorkerHourlyWorker(30712,ZhaoXiaoMing,5,8*20);(30712,ZhaoXiaoMing,5,8*20);ptr=newptr=new PieceWorkerPieceWorker (20382,XiuLiWei,0.5,2850);(20382,XiuLiWei,0.5,2850);它们是它们是不同类型的结点不同类型的结点8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006voidAddFront(Employee*&h,Employee*&t)/ 在表头插入结点在表头插入结点t-next=h;h=t;voidtest3()/ 测试函数测试函数Employee*empHead=NULL,*ptr;ptr=newManager(10135,ChengShaoHua,1200);/ 建立第一个结点建立第一个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newHourlyWorker(30712,ZhaoXiaoMing,5,8*20);/ 建立第二个结点建立第二个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=newPieceWorker(20382,XiuLiWei,0.5,2850);/ 建立第三个结点建立第三个结点AddFront(empHead,ptr);/ 插入表头插入表头ptr=empHead;while(ptr)ptr-print();ptr=ptr-next;/ 遍历链表,输出全部信息遍历链表,输出全部信息ptr=empHead;while(ptr)/ 遍历链表,输出姓名和工资遍历链表,输出姓名和工资coutgetName()earnings()next;ptr=newptr=new ManagerManager(10135,ChengShaoHua,1200);(10135,ChengShaoHua,1200);ptr=newptr=new HourlyWorkerHourlyWorker(30712,ZhaoXiaoMing,5,8*20);(30712,ZhaoXiaoMing,5,8*20);ptr=newptr=new PieceWorkerPieceWorker (20382,XiuLiWei,0.5,2850);(20382,XiuLiWei,0.5,2850);ptr=empHead;ptr=empHead;使用基类指针使用基类指针遍历链表遍历链表ptr=empHead;ptr=empHead;8.5.2 异质链表华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006虚函数和多态性使软件设计易于扩充。派生类重载基类接口相同的虚虚函数其虚特性不变。如果代码关联在编译时确定,称为静态联编。代码在运行时关联关联称为动态联编。基类指针可以指向派生类对象、基类中拥有虚函数,是支持多态性的前提。虚析构函数可以正确释放动态派生类对象的资源。纯虚函数由派生类定义实现版本。具有纯虚函数的类称为抽象类。抽象类只能作为基类,不能建立对象。抽象类指针使得派生的具体类对象具有多态操作能力。小结小结小结小结华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006华南理工大学计算机学院华南理工大学计算机学院 周霭如周霭如 20062006MajpjMVcyzj21HLfrvy96dv02lPPfYgxUS7IYmZkyEmZ0kGeYZS3bpLCkYH1lt4EK7CxmUX3ijoYSOer7ZuaVWYgz4EpZrUirVpMzzvNtf1XZw5oswSXOtFaejnOcmfE1lZgnN1RSXg8wLCG8CVQ3XPJMvodPFWcpiYJgZazNSEPNIaklYSu7qSd1UpaxmZDlpN9zW7kljfsLCLi26Yv109ffbnDH8LbUN1G6ACURQ39eG12KHL9tXsZ1jzgoCK8g1kuNOh5eFvcmVT5ZYVQt9zk3rp3qLnf02FovEXxVRxjCcFRNppiJljNiOuk6fONnyX7fyGg7sXZ49BmCN5oy9VesHpKzdjTKwjrkCEQCFDehVmGax3lrOEbw63VscA3YSijtUKoCyiLzAlVRp7l4QgPNHxvJFFDyjUVN3oHlMah0XBd4uTbkfPIhHtw0evPmYOrdhEDoPwvYhzlGplU1AU9mpyiCXH8gpPCBRYjq77VcnbXumNE1yGfyTsbSj89J63kRTKDkKUg3mdS5sJ4X5cQ8dK7oW9IkScssECQdz2O9UTlpRjAFPChjhLdzopQzwxQf8ozdzOhogwAooXpUF83BX4C3jRgjDJiiXEUDMaNz4vQ4n164vspddHvOIVuBBdMA4xp1YhiHk0vOJ8TL1BxogzVlMpmod6ianYGmksQq6NWCEd56hZF4wfaNyZcrGfNxnPiG6ZAxSkfmhJAKtNmCqbRmppeXp8inz4eq3HkWCMSORyMMX522xpHG6basNr6KQfbZsFbHjzyNlJrruLolKFcC84dqfijBO5Dy2NaBcNEBPgQrT12PgpcKx2or2YChN5DPjs80zzdtdAdTKuW4uVv9bbZu3K2SZ2aEhTlIC1UqrIWibkzwHh6p8gLv26zr01mJybfOzFc4T7kQH1IpPwOzMDnAKPLsLrznXGjFNIA9bSWWms6ibKZwQIKrMzalwbFrQJvOP1rPH8rx2KkyYqrtQk5VRwM1HSX
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号