您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 第 8 章(2)━━多态性与虚函数
C++程序设计第8章(2)━━多态性与虚函数主要内容C++的多态性动态多态性的实现条件虚函数的声明虚函数的特性与调用静态关联、动态关联虚析构函数纯虚函数抽象类综合实例C++的多态性多态性:指对不同类型的对象发送同样的消息(即调用同名的函数),不同类型的对象在接收时会产生不同的行为(即执行各自同名的函数)。编译时多态性(静态多态性):指在编译阶段,系统就可根据所操作的对象,确定其具体的操作。编译时多态性是通过函数重载、运算符重载来实现的。函数重载是根据函数调用式中所给出的实参的类型或实参的个数,在编译阶段系统就可确定调用的是同名函数中的哪一个。运算符重载是根据运算式中所给出的运算对象的类型,在编译阶段系统就可确定执行的是同种运算中的哪一个。运行时多态性(动态多态性):指在编译阶段,系统仅根据函数调用式是无法确定调用的是同名函数中的哪一个;必须在程序运行过程中,动态确定所要调用函数的当前对象,并根据当前对象的类型来确定调用的是同名函数中的哪一个。运行时多态性是通过“类的继承关系”加上“虚函数”联合起来实现的。动态多态性的实现条件要有类的继承层次结构:一个基类可以派生出不同的派生类,各派生类中可以新增与基类中的函数名字相同、参数个数及类型也相同的成员,这些同名的成员函数在不同的派生类中就有不同的含义!这样,在类的继承结构中,不同的层次上出现了名字相同、参数个数及类型也相同、但功能不同的函数!引入虚函数:作用是在由一个基类派生出的类体系中实现“一个接口,多种方法”,主要用于建立通用程序。对于同一类体系中的各层次派生类,使用虚函数可实现统一的类接口,以便用相同的方式对各层次派生类的对象进行操作。虚函数是基类的成员函数,是为了实现某一种功能而假设的虚拟函数,在该基类的各层次派生类中对该虚函数可有各自不同的定义!要能体现虚函数的特性:必须通过基类的对象指针、基类的对象引用来调用各层次派生类对象的同名虚函数,才能体现虚函数的特性!因为只有这样才能用相同的调用方式去调用不同层次派生类对象的同名虚函数,从而实现动态多态性。虚函数的声明虚函数的声明:class基类{…virtual返回值类型成员函数名(形参表){函数体}};①当一个基类的某成员函数声明为虚函数,则在该基类的所有派生类中,与虚函数同名、参数个数及类型相同、且返回值类型也相同的,不论是否有关键字virtual修饰,都是虚函数,反之不然。但要注意:若在派生类中只是与虚函数同名,而参数个数或类型有不同时,属于函数重载,不是虚函数!②virtual只是用在类中声明虚函数,若在类外定义虚函数前面不要加virtual。③构造函数、静态成员函数不能声明为虚函数!析构函数可以声明为虚函数。虚函数的特性与调用如何体现虚函数的特性?只有通过基类的对象指针、基类的对象引用来调用派生类对象的虚函数时,才能体现虚函数的特性!而通过派生类对象的对象名、对象指针、对象引用来调用虚函数时,无法体现虚函数的特性!派生类对象中一般成员函数的调用━━方法㈠:可通过派生类对象的对象名、对象指针、对象引用来调用!调用过程:若派生类新增成员函数中存在该函数,则被调用;若不存在,则调用上一层基类中的该函数;若这一层基类中也不存在,就继续往上一层寻找…,直至找到该函数并被调用。派生类对象中一般成员函数的调用━━方法㈡:可通过基类的对象指针、基类的对象引用来调用派生类对象中的一般成员函数!但只能调用派生类中从该基类继承过来的那部分成员函数!虚函数的特性与调用派生类对象中虚函数的调用━━方法㈠:派生类对象的虚函数也是成员函数,可按一般成员函数的方式调用!即:可通过派生类对象的对象名、对象指针、对象引用来调用!调用过程与一般成员函数的调用过程相同!由此可见,这种调用方式无法体现虚函数的特性!派生类对象中虚函数的调用━━方法㈡:可通过基类的对象指针、基类的对象引用来调用派生类对象的虚函数!调用过程:调用的是派生类中的虚函数!若派生类中没有重新定义该虚函数,则调用的是上一层基类中的该虚函数;若在这一层基类中也没有重新定义该虚函数,就继续往上一层寻找…,直至基类的对象指针、基类的对象引用它们本身所属的那一层基类!动态多态性的实现:可以让基类的对象指针(或基类的对象引用)先后指向(或先后引用)同一类族中不同派生类的对象,以便用相同的调用方式去调用不同派生类对象中的同名虚函数,从而实现动态多态性。【例】(派生类对象中一般成员函数的调用──方法㈠:可通过派生类对象的对象名、对象指针、对象引用来调用!注意调用过程。)#includeiostream.hclassA{intx;public:A(inta){x=a;}voidg(){cout“A::x=”xendl;}};classB:publicA{inty;public:B(inta,intb):A(a){y=b;}voidf(){cout“B::y=”yendl;}};classC:publicB{intm;public:C(inta,intb,intc):B(a,b){m=c;}voidg(){cout“C::m=”mendl;}};classD:publicC{intn;public:D(inta,intb,intc,intd):C(a,b,c){n=d;}voidf(){cout“D::n=”nendl;}};voidmain(){Dd1(1,2,3,4);d1.f();d1.g();D*pd=&d1;pd-f();pd-g();D&dd1=d1;dd1.f();dd1.g();}运行:D::n=4C::m=3D::n=4C::m=3D::n=4C::m=3从A类继承的成员:intx;g();不是虚函数从B类继承的成员:inty;f();不是虚函数从C类继承的成员:intm;g();不是虚函数D类新增的成员:intn;f();不是虚函数pdd1对象dd1【例】(派生类对象中虚函数的调用──方法㈠:可通过派生类对象的对象名、对象指针、对象引用来调用!注意调用过程与一般成员函数相同!由此可见,这种调用方式无法体现虚函数的特性!)#includeiostream.hclassA{intx;public:A(inta){x=a;}virtualvoidg(){cout“A::x=”xendl;}};classB:publicA{inty;public:B(inta,intb):A(a){y=b;}virtualvoidf(){cout“B::y=”yendl;}};classC:publicB{intm;public:C(inta,intb,intc):B(a,b){m=c;}voidg(){cout“C::m=”mendl;}};classD:publicC{intn;public:D(inta,intb,intc,intd):C(a,b,c){n=d;}voidf(){cout“D::n=”nendl;}};voidmain(){Dd1(1,2,3,4);d1.f();d1.g();D*pd=&d1;pd-f();pd-g();D&dd1=d1;dd1.f();dd1.g();}运行:D::n=4C::m=3D::n=4C::m=3D::n=4C::m=3从A类继承的成员:intx;g();虚函数从B类继承的成员:inty;f();虚函数从C类继承的成员:intm;g();虚函数D类新增的成员:intn;f();虚函数pdd1对象dd1【例】(派生类对象中一般成员函数的调用──方法㈡:可通过基类的对象指针、基类的对象引用来调用!但只能调用派生类中从该基类继承来的那部分成员函数!)#includeiostream.hclassA{intx;public:A(inta){x=a;}voidg(){cout“A::x=”xendl;}};classB:publicA{inty;public:B(inta,intb):A(a){y=b;}voidg(){cout“B::y=”yendl;}};classC:publicB{intz;public:C(inta,intb,intc):B(a,b){z=c;}voidg(){cout“C::z=”zendl;}voidf(){cout“Bye!”endl;}};voidmain(){Cc1(1,2,3);A*pa=&c1,&aa1=c1;pa-g();aa1.g();//pa-f();为什么不行?B*pb=&c1,&bb1=c1;pb-g();bb1.g();//pb-f();为什么不行?C*pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();}从A类继承的成员:intx;g();不是虚函数从B类继承的成员:inty;g();不是虚函数C类新增的成员:intz;g();不是虚函数f();不是虚函数pbpapcC1对象运行:A::x=1A::x=1B::y=2B::y=2C::z=3C::z=3Bye!【例】(派生类对象中虚函数的调用──方法㈡:可通过基类的对象指针、基类的对象引用来调用!注意:调用的是派生类中的虚函数!若派生类中没有重新定义该虚函数,则调用的是上一层基类中的该虚函数,…)#includeiostream.hclassA{intx;public:A(inta){x=a;}virtualvoidg(){cout“A::x=”xendl;}};classB:publicA{inty;public:B(inta,intb):A(a){y=b;}voidg(){cout“B::y=”yendl;}};classC:publicB{intz;public:C(inta,intb,intc):B(a,b){z=c;}voidg(){cout“C::z=”zendl;}virtualvoidf(){cout“Bye!”endl;}};voidmain(){Cc1(1,2,3);A*pa=&c1,&aa1=c1;pa-g();aa1.g();//pa-f();为什么不行?B*pb=&c1,&bb1=c1;pb-g();bb1.g();//pb-f();为什么不行?C*pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();}从A类继承的成员:intx;g();虚函数从B类继承的成员:inty;g();虚函数C类新增的成员:intz;g();虚函数f();虚函数pbpapcC1对象运行:C::z=3C::z=3C::z=3C::z=3C::z=3C::z=3Bye!【例】(请注意调用过程。)#includeiostream.hclassA{intx;public:A(inta){x=a;}virtualvoidg(){cout“A::x=”xendl;;}};classB:publicA{inty;public:B(inta,intb):A(a){y=b;}voidg(){cout“B::y=”yendl;}};classC:publicB{intz;public:C(inta,intb,intc):B(a,b){z=c;}virtualvoidf(){cout“Bye!”endl;}};voidmain(){Cc1(1,2,3);A*pa=&c1,&aa1=c1;pa-g();aa1.g();//pa-f();为什么不行?B*pb=&c1,&bb1=c1;pb-g();bb1.g();//pb-f();为什么不行?C*pc=&c1,&cc1=c1;pc-g();cc1.g();pc-f();}从A类继承的成员:intx;g();虚函数从B类继承的成员:inty;g();虚函数C类新增的
本文标题:第 8 章(2)━━多态性与虚函数
链接地址:https://www.777doc.com/doc-3566650 .html