多态与虚函数 例题
c++多态性与虚函数习题

作业题一、写出下列程序运行结果1.#include<iostream>using namespace std;class A {public:virtual void func( ) {cout<<”func in class A”<<endl;} };class B{public:virtual void func( ) {cout<<”func in class B”<<endl;} };class C:public A,public B{public:void func( ) {cout<<”func in class C”<<endl:}};int main( ){C c;A& pa=c;B& pb=c;C& pc=c;pa.func( );pb.func( );pc.func( );}2.#include<iostream>using namespace std;class A{public:virtual ~A( ){cout<<”A::~A( ) called “<<endl; }};class B:public A{char *buf;public:B(int i) { buf=new char[i]; }virtual ~B( ){delete []buf;cout<<”B::~B( ) called”<<endl;}};void fun(A *a) {delete a;}int main( ){ A *a=new B(10);fun(a);}二、程序设计题1有一个交通工具类vehicle,将它作为基类派生小车类car、卡车类truck和轮船类boat,定义这些类并定义一个虚函数用来显示各类信息。
5.2定义一个shape抽象类,派生出Rectangle类和Circle类,计算各派生类对象的面积Area( )。
【C++面向对象的程序设计】6多态性

虚析构函数
析构函数的作用是对象撤销之后清理现场。 在派生类对象撤销时,一般先调用派生类的 析构函数。再调用基类的析构函数。
然而,当定义的是一个指向基类的指针变量, 使用new运算符建立临时对象时,如果基类 中有析构函数,则在使用delete析构时只会 调用基类的析构函数。
这就需要将基类中的析构函数声明为虚函数。
虚函数的声明与使用
声明虚函数的一般格式如下: virtual 函数原型;
⑴ 必须首先在基类中声明虚函数。 ⑵ 派生类中与基类虚函数原型完全相同的成员函 数,即使在说明时前面没有冠以关键字virtual也 自动成为虚函数。
声明虚函数
⑶ 只有非静态成员函数可以声明为虚函数。 ⑷ 不允许在派生类中定义与基类虚函数名字及参数 特征都相同,仅仅返回类型不同的成员函数。 编译时 出错。 ⑸ 系统把函数名相同但参数特征不同的函数视为不 同的函数。 ⑹ 通过声明虚函数来使用C++提供的多态性机制时, 派生类应该从它的基类公有派生。
构函数等内容。
本章内容
静态联编与动态联编 虚函数的声明与使用 纯虚函数和抽象类 虚析构函数
Hale Waihona Puke 静态联编与动态联编所谓联编(tinding),就是使一个计算机程序的不同部 分彼此关联的过程。
静态联编在编译阶段完成,因为所有联编过程都在程 序开始运行之前完成,因此静态联编也叫先前联编或早期 联编。
另一种情况编译程序在编译时并不确切知道应把发送 到对象的消息和实现消息的哪段具体代码联编在一起,而 是在运行时才能把函数调用与函数体联系在一起,则称为 动态联编。
动态联编的实现
C ++语言中的动态联编是通过使用虚函数表 (Virtual Function Table)来实现的,虚函数表也称 为v-表。
C++(练习)第9章,多态性与虚函数

B虚函数
C派生类
D其他都不对
参考答案
A
5.关于虚函数的描述中,()是正确的。
A虚函数是一个静态成员函数
B虚函数是一个非成员函数
C虚函数既可以在函数说明时定义,也可以在函数实现时定义
D派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型
参考答案
D
6.下面4个选项中,()是用来声明虚函数的。
C virtual void tt(int);
D virtual void tt(int){ };
参考答案
A
二.填空题
1.如果类包含了一个或多个__1__,则它是抽象类。
参考答案
1:纯虚函数
2.虚函数必须是类的__1__。
参考答案
1:非静态成员函数或成员函数
3.多态性分为两类:编译时的多态性和__1__的多态性。
参考答案
1:友元函数
7.如果在类中定义了一个成员函数为__1__,则表明在该继承层次链条的派生类中有可能重新定义这个成员函数的实现,即它可能被派生类的同名函数所覆盖。
参考答案
1:虚函数
8.动态多态性通过__1__实现。
参考答案
1:虚函数
9.定义一个函数名为fun,返回值为int,没有参数的纯虚函数的定义是__1__。
参考答案
1:引用或指针
20.含有纯虚函数的类称为__1__。
参考答案
1:抽象类
21.在C++中,编译时的多态性是通过函数重载和__1__体现的。
参考答案
1:模板
三.问答题
四.编程题
参考答案
1:纯虚函数
12.虚函数必须是类的__1__。
《Java程序设计案例教程》第十章练习答案

第10章多态性与虚函数一、单项选择题1.实现运行时的多态性要使用(D)。
A.重载函数B.构造函数C.析构函数D.虚函数2.通过运算符重载,可以改变运算符原有的(A)。
A.操作数类型B.操作数个数C.优先级D.结合性3.将运算符重载为类成员函数时,其参数表中没有参数,说明该运算符是(B)。
A.不合法的运算符B.一元运算符C.无操作数的运算符D.二元运算符4.在重载一个运算符时,其参数表中没有任何参数,说明该运算符是(B)。
A.作为友元函数重载的一元运算符B.作为成员函数重载的一元运算符C.作为友元函数重载的二元运算符D.作为成员函数重载的二元运算符5.如果表达式++a中的"++"是作为成员函数重载的运算符,若采用运算符函数调用格式,则可表示为(D)。
A.a.operator++(1)B.operator++(a)C.operator++(a,1)D.a.operator++()6.如果表达式a>=b中的">="是作为非成员函数重载的运算符,则可以等效地表示为(C)。
A.a.operator>=(b)B.b.operator>=(a)C.operator>=(a,b)D.perator>=(b,a)7.有如下程序:#include<iostream>using namespace std;class A{public:virtual void funl (){cout<<"A1";}void fun2 (){cout<<"A2";}};class B: public A{public:void funl (){cout<<"Bl";}void fun2 (){cout<<"B2";}};int main(){A*p=new B;p->funl ();p->fun2();return 0;}程序执行后,输出结果为(C)。
实验三 虚函数与多态 纯虚函数(完整版)

实验三虚函数与多态、纯虚函数一.实验目的1. 在掌握继承与派生关系的基础上,进一步理解虚函数与多态性的关系,实现运行时的多态。
2. 学会定义和使用纯虚函数二、实验容1.例:了解"单接口,多方法"的概念。
现有称为figure的基类,存放了各二维对象(三角形、矩形和圆形三个类)的各维数据,set_dim()设置数据,是标准成员函数。
show_area()为虚函数,因为计算各对象的面积的方法是不同的。
【程序】#include < iostream >using namespace std;class figure{protected:double x,y;public:void set_dim(double i,double j=0){ x=i; y=j; }virtual void show_area(){ cout<<"No area computation defined for this class.\n";}};class triangle:public figure{void show_area(){ cout<<"Triangle with height "<< x<<" and base "<< y<<" has an area of "<< x*0.5*y<< endl;}};class square:public figure{public:void show_area(){ cout<<"Square with dimensions "<< x<<" and "<< y<<" has an area of "<< x*y<< endl;}};class circle:public figure{public:void show_area(){ cout<<"Circle with radius "<< x<<" has an area of "<<3.14159*x*x<< endl;}};int main(){figure *p;triangle t;square s;circle c;p->set_dim(10.0,5.0);p->show_area();p=&s;p->set_dim(10.0,5.0);p->show_area();p=&c; p->set_dim(10.0);p->show_area();return 0;}【要求】(1)建立工程,录入上述程序,调试运行并记录运行结果。
实验七 虚函数及应用

实验七虚函数及应用一、实验目的1.理解虚函数与运行时(动态)多态性之间的关系,掌握虚函数的定义及应用;2.理解纯虚函数与抽象类的概念,掌握抽象类的定义及应用;3.理解虚析构函数的概念及作用。
二、实验学时课内实验:2课时课外练习:2课时三本实验涉及的新知识㈠虚函数与动态多态性在C++中,如果将基类与派生类的同名成员函数定义为虚函数,就可以定义一个基类指针,当基类指针指向基类对象时访问基类的成员函数,当基类指针指向派生类对象时访问派生类的成员函数,实现在运行时根据基类指针所指向的对象动态调用成员函数,实现动态多态性。
换句话说,虚函数与派生类相结合,使C++能支持运行时(动态)多态性,实现在基类中定义派生类所拥有的通用“接口”,而在派生类中定义具体的实现方法,即“一个接口,多种方法”。
㈡虚函数的定义1.在基类中定义在定义函数的前面加上“virtual ”。
即:virtual 返回类型函数名(参数表){ …… }2.在派生类中定义函数的返回类型、函数名、参数的个数、参数类型及顺序必须与基类中的原型完全相同。
3.说明:⑴在派生类中定义虚函数时,可用“virtual”也可不用“virtual”(最好都使用)。
⑵虚函数在派生类中重新定义时,其原型必须与基类中相同。
⑶必须用基类指针访问虚函数才能实现运行时(动态)多态性;当用普通成员函数的调用方法(即用圆点运算符)调用虚函数时,为静态调用;⑷虚函数在自身类中必须声明为成员函数(不能为友元函数或静态成员函数),但在另一个类中可以声明为友元函数。
⑸虚函数可以公有继承多次,其虚函数的特性不变。
⑹构造函数不能定义为虚函数,但析构函数可以定义为虚函数。
⑺虚函数与重载函数的关系①普通函数重载是通过参数类型或参数的个数不同实现的;重载一个虚函数时,其函数原型(返回类型、参数个数、类型及顺序)完全相同。
②当重载的虚函数只有返回类型不同时,系统将给出错误信息;如果定义的虚函数只有函数名相同,而参数个数或类型不同时,则为普通函数重载。
C++多态练习题

C++多态练习题⼀、填空题(1)C++的两种联编⽅式为:动态联编和静态联编。
(2)C++⽀持两种多态性,静态联编所⽀持的多态性被称为编译时的多态性、动态联编所⽀持的多态性被称为运⾏时的多态性。
(3)重载函数在编译时表现出多态性,是静态联编;⽽虚函数则在运⾏时表现出多态性是动态联编。
(4)为了区分重载函数,把⼀个派⽣类中重定义基类的虚函数称为覆盖。
(5)如果派⽣类与基类的虚函数仅仅返回类型不同,其余相同,则c++认为是使⽤了不恰当的虚函数。
(6)在构造函数和析构函数中调⽤虚函数时,采⽤静态联编。
(7)纯函数的定义是在虚函数定义的基础上,再让函数等于0 。
(8)对于包含有纯虚函数的类被称为抽象类。
⼆、选择题(⾄少选⼀个,可以多选)(1)⽤关键字(A)标记的函数被称为虚函数。
A.virtualB.privateC.publicD.protected(2)在C++中,要实现动态联编,必须使⽤(D)调⽤虚函数。
A.类名B.派⽣类指针C.对象名D.基类指针(3)下列函数中,可以作为虚函数的是(BD)。
A.普通函数B.⾮静态成员函数C.构造函数D.析构函数(4)在派⽣类中,重载⼀个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值(B)。
A.不同B.相同C.相容D.部分相同(5)使⽤虚函数保证了在通过⼀个基类类型的指针(含引⽤)调⽤⼀个虚函数时,c++系统对该调⽤进⾏(A),但是,在通过⼀个对象访问⼀个虚函数,使⽤(B)。
A.动态联编B.静态联编C.动态编译D.静态编译(6)下⾯函数原型声明中,(C)声明的fun()为纯虚函数。
A.void func()=0;B.virtual void func()=0;B.virtual void func();C.virtual void func(){};(7)若⼀个类中含有纯虚函数,则该类称为(C)。
A.基类B.虚基类C.抽象类D.派⽣类(8)假设Myclass为抽象类,下列声明(CD)是错误的。
虚 函 数

(6)一个虚函数无论被公有继承多少次,它仍然保持其 虚函数的特性。
my_base--------
10 20
从程序运行的结果可以看出,虽然执行语句mp=&mc;后, 指针mp已经指向了对象mc,但是它所调用的函数(mp>show()),仍然是其基类对象的show(),显然这不是我 们所期望的。出现这个问题的原因以及解决方法,我 们将在下一节介绍。在此先说明引入派生类后,使用 对象指针应注意的几个问题:
derive op2; //定义派生类derive的对象op2
ptr=&op1;
//使指针ptr指向对象op1
ptr=&op2;
//错误,不允许将base类指针ptr指
向它的私有派生类//对象op2
//…
}
(2)允许将一个声明为指向基类的指针指向公有派生类
的对象,但是不能将一个声明为指向派生类对象的指 针指向其基类的对象。
(3)声明为指向基类的指针,当其指向公有派生的
对象时,只能用它来直接访问派生类中从基类继承来
的成员,而不能直接访问公有派生类中定义的成员,
例如:
class A { //... public: void print1(); }; class B:public A{ //... public: print2(); };
可见,虚函数同派生类的结合和使C++支持运行时的多 态性,而多态性对面向对象的程序设计是非常重要的, 实现了在基类定义派生类所拥有的通用接口,而在派 生类定义具体的实现方法,即常说的“同一接口,多 种方法”。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
题目:水果类与虚函数多态与虚函数例题
1.题目内容与要求
①首先设计一个水果类(Fruit)作为基类,成员函
数为显示“水果”函数;
②然后设计Fruit类的四个派生类:香蕉类
(Banana)、苹果类(Apple)、梨子类(Pear)和桃子类(Peach),成员函数分别为显示“香
蕉”、“苹果”、“梨子”和“桃子”函数;
③最后在主函数中定义这些类的对象,并调用它们
的显示函数。
2.类的分析
主函数
水果类对象 香蕉类对象 苹果类对象 梨子类对象 桃子类对象 显示函数调用
水果类
显示函数
香蕉类
显示函数
苹果类
显示函数
梨子类
显示函数
桃子类
显示函数
3.类的设计
main
Fruit f; Banana b; Apple a; Pear p; Peach ph; f=b; f.print(); f=a; f.print(); ……
Fruit
print
Banana
print
Apple
print
Pear
print
Peach
print
4.基类程序代码// 基类: 水果类
class Fruit
{
public:
void print() {
cout<< "水果" <<endl; }
};
// 派生类1: 香蕉类
class Banana: public Fruit{ public:
void print() {
cout<< "香蕉" <<endl;
} };
// 派生类2: 苹果类
class Apple: public Fruit{ public:
void print() {
cout<< "苹果" <<endl;
} };
派生类程序代码
// 派生类3: 梨子类
class Pear: public Fruit{ public:
void print() { cout<< "梨子" <<endl;
} };
// 派生类4: 桃子类
class Peach: public Fruit{ public:
void print() { cout<< "桃子" <<endl;
} };
#include <iostream> using namespace std; <5个类的定义在此!>
int main() // 主函数 {
核心代码在此!
return 0; }
主函数程序代码
Fruit * pFruit[] = { new Fruit(),
new Banana(), new Apple(), new Pear(), new Peach() };
for(int i = 0; i < 5; i++) { (*pFruit[i]).print(); }
❝
从以上5行运行结果来看,似乎调用的都是基类的print 函数。
❝
究其原因是派生类函数未能覆盖基类同名函数,从而造成没有机会调用派生类函数的情况。
5.运行结果与程序分析
6. 延伸思考
问题
怎样实现派生类函数的调用呢?
答案
使用virtual修饰符改写基
类Fruit的print为虚函数
!
详细格式
virtual void print ()
修改后的基类程序代码// 基类: 水果类
class Fruit
{
public:
virtual void print() {
cout<< "水果" <<endl;
}
};
7.小结
✓虚函数是多态的一种实现形式;
✓作用是实现函数的覆盖;
✓写法是将virtual加在函数之前;
✓今后在类的继承当中的基类尽量多使用虚函数。