多态与虚函数 例题

合集下载

多态练习题

多态练习题

1、生成表示学生的类XS,提供成员函数dispXM()、dispXB()和dispNL()分别用来显示姓名、性别和年龄,并将他们全部定义为纯虚函数;生成CZS类表示初中生,包含数据成员xm、xb和nl表示学生的姓名、性别和年龄,提供成员函数dispXM()、dispXB()和dispNL()分别用来显示姓名、性别和年龄;再生成类GZS表示高中生和类DXS表示大学生,同样包含相同含义的数据成员xm、xb和nl,也包括成员函数dispXM()、dispXB()和dispNL()。要求:

(1)设计和实现基本类XS

(2)设计和实现派生类CZS,GZS和DXS

(3)分别生成CZS、GZS、DXS类对象

(4)将CZS、GZS、DXS类对象的指针赋给指针赋给XS类的指针变量。

(5)分别用XS类的指针和引用访问dispXM()、dispXB()和dispNL()函数。

(6)观察程序结果。

#include <iostream>

#include <string.h>

using namespace std;

class XS{

public:

virtual void dispXM()=0;

virtual void dispXB()=0;

virtual void dispNL()=0;

};

class CZS:public XS{

public:

CZS(char * m="张三",int b=1,int n=14);

void dispXM();

void dispXB();

void dispNL();

简述虚函数实现多态的原理

简述虚函数实现多态的原理

简述虚函数实现多态的原理

虚函数是C++中支持多态的一种机制,多态是指同一函数在不同对象上产生不同的行为。虚函数实现多态的原理是通过使用虚表(Vtable)和虚指针(Vptr)实现。

虚表是一个指针数组,它保存了类中所有虚函数的地址。当一个对象被创建时,会在其内存布局中添加一个指向该类虚表的虚指针。当调用一个虚函数时,编译器会通过该对象的虚指针查找对应虚表,进而找到虚函数的地址,然后执行该函数。

使用虚函数实现多态的过程如下:

1. 定义一个基类,并将其中需要实现多态的成员函数声明为虚函数。

2. 派生出子类,并根据需要重写基类的虚函数。

3. 通过基类指针或引用调用虚函数时,编译器会根据实际对象类型确定调用哪个版本的虚函数。

由于虚函数是在运行时才确定的,所以可以实现动态绑定,使程序具有更高的灵活性和可扩展性。

C--程序设计--第10章-多态性及虚函数

C--程序设计--第10章-多态性及虚函数
例: c1+c2=6+1i
c1-c2=-2+5i
问题:用友元函数代替成员函数,重新编写上例。
#include <iostream.h>
inlcilnaescsomcpolmepxlecxomplex::operator +(const complex &c)
vo{id {rmpeautibunrl(ni)cc:omplex(real+c.real,imag+c.imag);
动态联编 虚函数
一、 函数重载
是多态性的一种体现
如,汽车都有方向盘,加运算等
函数重载就是赋给同一个函数名多个含义。 重载函数的意义在于可以用相同的函数名
访问一组相互关联的函数。 成员函数重载
程序运行结果为:
T1h5例is1i0s .a1d:emo.
That is a program. 18 问题:定义一个string类,对其中的构造函数进行重载。
使用重载函数注意:
不要使用重载函数描述不相干的函数 在类中,构造函数和普通成员函数均可以
重载 避免与函数的默认参数产生二义性
二、运算符重载
运算符重载(operate overloading)就是 赋予已有的运算符多重含义。
运算符重载实质是函数重载,运算符重载 的选择与函数重载类似,会根据运算符的 操作数的类型、个数和顺序来进行运算符 函数的选择。

【C++面向对象的程序设计】6多态性

 【C++面向对象的程序设计】6多态性

什么情况下要使用虚函数
首先看成员函数所在的类是否会被作为基类。然后 看成员函数在类的继承中有无可能被更改功能,如 果希望改其功能,一般会被声明为虚函数。
如果成员函数在类被继承之后功能不变,或者派生 类用不到该函数,则不必把它声明为虚函数。
应考虑对成员函数的调用是通过对象名还是通过基 类指针或者引用,如果是通过基类指针或引用调用, 则应当把它声明为虚函数。
动态联编的实现
C ++语言中的动态联编是通过使用虚函数表 (Virtual Function Table)来实现的,虚函数表也称 为v-表。
每个类的实例都有一个隐含的指向该类v-表的指 针,当执行诸如a_p -> show()这样的语句时,系统 首先取a_p所实际指向的对象中的v-表指针,然后调 用由这个v-表中指针项所指定的函数show(),从而实 现了对不同类的虚函数的调用。
虚析构函数
析构函数的作用是对象撤销之后清理现场。 在派生类对象撤销时,一般先调用派生类的 析构函数。再调用基类的析构函数。
然而,当定义的是一个指向基类的指针变量, 使用new运算符建立临时对象时,如果基类 中有析构函数,则在使用delete析构时只会 调用基类的析构函数。
这就需要将基类中的析构函数声明为虚函数。
纯虚函数和抽象类
为什么要使用纯虚函数? 纯虚函数的作用是在基类中为其派生类保留某

C++练习题 多态

C++练习题 多态
ห้องสมุดไป่ตู้
C++练习题 多态
1. 计算三角形,正方形和圆形三种图形的面积,周长 提示:设计基类shape,让三角形、正方形、圆形均继承自此类。 在shape中实现相应的计算面积、周长的虚函数,然后在子类中改写 这些虚函数。 2. 车辆类,派生小轿车,卡车,吉普车,收费站对来往车辆收费 提示:思路与上题类似 3.写一个程序,建立两个类型的表,队列和堆栈,使它们可以通过 共用的接口访问。 list stack queue store() retrieve() 提示:此题可以先构建一个抽象类list,其内部申明公共接口为纯 虚函数。然后队列和堆栈继承自list并改写这些纯虚函数。

第六章 多态性与虚函数

第六章 多态性与虚函数

Rectangle Draw()
void main() {
Circle Draw()
Graphic * agraphic; Rectangle * arect=new Rectangle(); agraphic=arect; agraphic->Draw(); Circle * acircle=new Circle(); agraphic=acircle; agraphic->Draw(); }
void main() { Graphic g; g.Draw(); Rectangle * arect=new Rectangle(); arect->Draw(); Graphic *p=arect; p->Draw(); }
课后作业
1、武器中有手枪,大炮和导弹等,这些武器都 有发射功能。 请用纯虚函数和抽象类的概念来设计他们。
第六章 多态性与虚函数
Graphic Draw()
继承中的指针
class Graphic{ public: void Draw() {cout<<"draw a graphic now "<<endl;} }; class Rectangle:public Graphic{ public: void Draw() {cout<<"draw a rectangle now "<<endl;} }; class Circle:public Graphic{ public: void Draw() {cout<<"draw a circle now "<<endl;} };

C 程序设计与应用基础第五章 多态性习题答案

C  程序设计与应用基础第五章 多态性习题答案
List *head, *tail, *next;
int num;
};
class Quene:public List
{
public:
void Store(int i);
int Retrieve();
};
void Quene::Store(int i)
{
List *item;
item=new Quene;
{
cout<<"请输入"<<name<<"本月的工作时间:";
cin>>workHours;
Pay=hourlyRate*workHours;
cout<<"兼职技术人员"<<name<<"的编号为:"<<no<<"\t本月工资为:"<<Pay<<endl;
}
void technician::display()
Base's des.
根据结果将程序补充完整。
#incude <iostream.h>
class Base
{
public:
Base(){cout<<"Base's cons."<<endl;}

C++多态练习题

C++多态练习题

C++多态练习题

⼀、填空题

(1)C++的两种联编⽅式为:动态联编和静态联编。

(2)C++⽀持两种多态性,静态联编所⽀持的多态性被称为编译时的多态性、动态联编所⽀持的多态性被称为运⾏时的多态性。

(3)重载函数在编译时表现出多态性,是静态联编;⽽虚函数则在运⾏时表现出多态性是动态联编。

(4)为了区分重载函数,把⼀个派⽣类中重定义基类的虚函数称为覆盖。

(5)如果派⽣类与基类的虚函数仅仅返回类型不同,其余相同,则c++认为是使⽤了不恰当的虚函数。

(6)在构造函数和析构函数中调⽤虚函数时,采⽤静态联编。

(7)纯函数的定义是在虚函数定义的基础上,再让函数等于0 。

(8)对于包含有纯虚函数的类被称为抽象类。

⼆、选择题(⾄少选⼀个,可以多选)

(1)⽤关键字(A)标记的函数被称为虚函数。

A.virtual

B.private

C.public

D.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()为纯虚函数。

多态与虚函数 练习题

多态与虚函数 练习题

多态与虚函数练习

选择题

单选题

1.要实现动态多态性,可以通过()调用虚函数。

A. 基类指针

B. 成员名限定

C. 对象名

D. 派生类名

2.以下()成员函数表示纯虚函数。

A. virtual int vf(int);

B. void vf(int)=0;

C. virtual void vf()=0;

D. virtual void vf(int) { };

3.关于纯虚函数和抽象类的描述中,错误的是()。

A. 纯虚函数是一种特殊的虚函数,它没有具体的实现

B. 抽象类是指具有纯虚函数的类

C. 一个基类中说明有纯虚函数,该基类派生类一定不再是抽象类

D. 抽象类只能作为基类来使用,其纯虚函数的实现由派生类给出

4.下面4个选项中,()是用来声明虚函数的。

A. virtual

B. public

C. using

D. false

5.下列关于动态联编的描述中,错误的是()。

A. 动态联编是以虚函数为基础

B. 动态联编是运行时确定所调用的函数代码的

C. 动态联编调用函数操作是指向对象的指针或对象引用

D. 动态联编是在编译时确定操作函数的

6.关于虚函数的描述中,()是正确的。

A. 虚函数是一个静态成员函数

B. 虚函数是一个非成员函数

C. 虚函数既可以在函数说明时定义,也可以在函数实现时定义

D. 派生类的虚函数与基类中对应的虚函数具有相同的参数个数和类型

7.下面关于友元的描述中,错误的是()。

A. 友元函数可以访问该类的私有数据成员

B. 一个类的友元类中的成员函数都是这个类的友元函数

C. 友元可以提高程序的运行效率

虚 函 数

虚 函 数

例4-14 #include<iostream.h> class my_base{ int a,b; public: my_base(int x,int y) {a=x; b=y; } virtual void show()
show() {cout<<"my_base--------\n"; cout<<a<<" "<<b<<endl; } };
可见,虚函数同派生类的结合和使C++支持运行时的多 态性,而多态性对面向对象的程序设计是非常重要的, 实现了在基类定义派生类所拥有的通用接口,而在派 生类定义具体的实现方法,即常说的“同一接口,多 种方法”。
2.虚函数的定义 虚函数就是在基类中被关键字virtual说明,并在派生类中重新定
义的函数。在派生类中重新定义时,其函数原型,包括返回类型、 函数名、参数个数与参数类型的顺序,都必须与基类中的原型完 全相同。 例4-15 # include<iostream.h> class parent{ protected: char version; public: parent() { version='A'; }
(7)虚函数必须是其所在类的成员函数,而不 能是友元函数,也不能是静态成员函数,因为 虚函数调用要靠特定的对象来决定该激活哪个 函数。但是虚函数可以在另一个类中被声明为 友元函数。

第7部分 多态性与虚函数

第7部分  多态性与虚函数

修改二(用指针实现)
void main() { Base b(5); Derive d(10,15); call(&b); call(&d); } 运行结果: 5 25
1、 一般虚函数成员
(1)一般虚函数成员的声明语法是: virtual 函数类型 函数名(形参表) {函数体} 在类外定义虚函数时,不加virtual。 (2)在派生类中重新定义此函数,要求函数名、函数类型、函数参 数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新 定义函数体。 (3)C++规定,当一个成员函数被声明为虚函数后,其派生类中的 同名函数都自动成为虚函数。因此在派生类重新声明该虚函数时, 可以加virtual,也可以不加。 如果在派生类中没有对基类的虚函数重新定义,则派生类简单地继 承其直接基类 直接基类的虚函数。 直接基类
(4)本质 本质不是重载声明而是覆盖。 本质 (5)调用方式:通过基类指针或引用,执行时会根据指针指向的对象的类 指针指向的对象的类, 指针指向的对象的类 决定调用哪个函数。 (6)如果通过对象名调用虚函数,属于静态关联;如果是通过基类指针调 用虚函数,则为动态关联。 (7)只有虚函数是动态绑定的,如果派生类需要修改基类的行为,就应该 在基类中将相应的函数声明为虚函数。 (8)一般不要重写继承而来的非虚函数。 8 (9)在重写继承来的虚函数时,如果函数有默认形参值,千万不要重新定 义不同的值。原因是:虽然虚函数是动态绑定的,但默认形参值是静态绑 定的。也就是说,通过一个指向派生类对象的基类指针,可以访问到派生 但默认形参值却只能来自基类的定义。 类的虚函数,但默认形参值却只能来自基类的定义 但默认形参值却只能来自基类的定义 (10)指向基类的指针仅能访问派生类中的基类部分。 (11)当基类析构函数调用虚函数时,不会调用派生类的虚函数。因为当 基类被析构时,对象已经不再是一个派生类对象了。

05.多态_练习题

05.多态_练习题
高质量C++编程练习题
1
第5章 多态练习
多态练习: 第一部分 第二部分
时间:6 学时
教学方法:学员练习
2
第5章 多态_练习 part1

1、【基本题】定义一个Person类,它包含数据成员age, name和gender。从Person中派生一个类Employee,在新类 中添加一个数据成员,存储个人的number.再从Employee中 派生一个类Executive,每个派生类都应该定义一个函数,来显 示相关的信息(名称和类型,如”Fred Smith is an Employee”)。编写一个main()函数,生成两个数组,一个 数组包含5个Executive对象,另一个数组包含5个一般的 Employee对象,然后显示它们的信息。另外,调用从 Employee类继承的成员函数,显示Executive信息。 2.【基本题】设计一个图书管理系统,基类为类Book,要求有书 名和作者属性, 由Book类派生子类AudioBook(有声书,需 要具有演说者属性),对于Book和AudioBook进行合理的属 性及行为的抽象,同时实现该类的print函数(注意,类体系 中的每个类都要设计合适的构造函数和析构函数)
5
第5章 多态_练习part2 -2/2
4. 【基本题】 Shape类是一个表示形状的抽象类,其中 GetArea()为求图形面积的纯虚函数。从Shape类派生三角形 类(Triangle)、矩形类(Rectangle),椭圆类(Ellipse)并重写 GetArea()函数完成求面积的功能。 – GetTotalArea(…)则是一个用以求不同形状的图形面积总 和的函数,完成该函数。 – 写出main函数:创建多个三角形或矩形或椭圆对象(个数不 定,由用户的输入指定),并调用GetTotalArea()函数求出 它们的总面积。(注意使用多文件结构) – 提示: • 1. GetTotalArea(…)应设计成全局函数

面向对象程序设计语言C虚函数和多态性

面向对象程序设计语言C虚函数和多态性

第七章 虚函数和多态性
• 7.1 虚函数
静态多态性 对于普通成员函数的重载,可表达为下面的方式: (1)在同一个类中重载; (2)在不同类中重载; (3)基类的成员函数在派生类中重载; 因此,重载函数的访问是在编译时区分的,这种程
序运行之前就能够在多个函数中确定当前访问的 函数的方法称为静态多态性。
第七章 虚函数和多态性
• 7.1 虚函数
虚函数与多态性
class Base { public:
Base(int a) {x=a;} void who() { cout << "base "<<x<<"\n";} protected: int x; };
class First_d: public Base { public:
第七章 虚函数和多态性
• 7.1 虚函数
静态多态性
C Cobj;
Cobj.fun();
//调用C::fun()
Cobj.B::fun(); //调用B::fun()
Cobj.A::fun(); //调用A::fun()
A & Aref=Cobj;
Aref.fun();
//调用A::fun() ,编译器通过类型确定调用哪个版本
First_d (int a ):Base(a) { } void who() { cout << "First derivation " <<x<<"\n";} }; class Second_d :public Base { public: Second_d (int a):Base(a) { } void who() { cout << "Second derivation " <<x<<"\n";} };

Ch8 多态、虚函数

Ch8 多态、虚函数
第八章
多态,虚函数与模版
(Virtual Function)
本节课的学习内容
8.1 多态性
基类和派生类 继承召唤多态: 继承召唤多态:同化效应 什么是多态 需要解决的问题
8.2 虚函数
什么是虚函数? 什么是虚函数? 虚函数的表达式 为什么选择虚函数?虚函数是如何实现多态性的? 为什么选择虚函数?虚函数是如何实现多态性的? 例子与几点建议 纯虚函数与抽象类
8.1.4 需要解决的问题(续)
这里我们只需要比较方案2与方案4: 类型域的致命弱点:它需要依靠程序员 按照确定的方式去操纵这些类型,而所 用的方式是编译器无法检查的. 虚函数能克服类型域解决方案中的缺陷, 它使程序员可以在基类里声明一些能够 在各个派生类里重新定义的函数.编译 器和装载程序能保证对象和应用于它们 的函数之间的正确对应关系.
8.2.4 覆盖与增大
-面向对象的程序设计(续)
虚函数允许派生类取代基类所提供的实现, 可以完全地取代(覆盖),也可以部分地取 代(增大). 这样,就使得虚函数可以是在还没有考虑到 特定的派生类之前写好并编译好的.
8.2.5 对虚函数的总结
对虚函数的总结: 要想在C++里取得多态性的行为,被调用的函数就必 须是虚函数; 多态必须是通过指向基类的指针或引用来操作对象; 指向基类的指针在操作它的多态类对象时,会根据不 同的类对象,调用其相应的函数,这个函数就是虚函 数; 如果使用了虚函数,编译器和装载程序能保证基类对 象和应用于它们的函数之间的正确对应关系; 虚函数是用C++进行面向对象程序设计的核心.

C++继承,虚函数与多态性专题

C++继承,虚函数与多态性专题

本文作者:黄邦勇帅

学习本文首先你应熟悉C++中的构造函数,基本的类的声明及怎样初始化类,关于这些问题,请参看本人所作的《C++构造函数,复制构造函数和析构函数》一文,在这篇文章中作了详细的介绍。

本文分两部分即继承和虚函数与多态性,本文第一部分详细讲解了继承时的构造函数和析构函数的问题,父类与子类的同名变量和函数问题,最后介绍了多重继承与虚基类。本文第二部分重点介绍了虚函数与多态性的问题,因此学习虚函数的基础是继承,因此在学习虚函数前应学好继承。本文详细易懂,内容全面,是学习C++的不错的资料。

本文内容完全属于个人见解与参考文现的作者无关,其中难免有误解之处,望指出更正。

声明:禁止抄袭本文,若需要转载本文请注明转载的网址,或者注明转载自“黄邦勇帅”。

主要参考文献:

1、C++.Primer.Plus.第五版.中文版[美]Stephen Prata著孙建春韦强译人民邮电出版社2005年5月

2、C++.Primer.Plus.第四版.中文版Stanley B.Lippman、Barbara E.Moo著李师贤等译人民邮电出版社2006年3月

3、C++.Primer.Plus.第三版.中文版Stanley B.Lippman等著潘爱民张丽译中国电力出版社2002年5月

4、C++入门经典第三版[美]Ivor Horton著李予敏译清华大学出版社2006年1月

5、C++参考大全第四版[美]Herbert Schidt著周志荣朱德芳于秀山等译电子工业出版社2003年9月

6、21天学通第四版C++ [美]Jesse Liberty著康博创作室译人民邮电出版社2002年3月

c多态性与虚函数习题

c多态性与虚函数习题
2.5为什么析构函数总是要求说明为虚函数?
3.选择题
3.1在C++中,要实现动态联编,必须使用(D)调用虚函数。
A.类名B.派生类指针C.对象名D.基类指针
3.2下列函数中,不能说明为虚函数的是()。
A.私有成员函数B.公有成员函数C.构造函数D.析构函数
3.3在派生类中,重载一个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值()。
A.虚析构函数B.虚构造函数
C.纯虚函数D.静态成员函数
3.6以下基类中的成员函数,哪个表示纯虚函数(C)。
A.virtual void vf(int);B.void vf(int)=0;
C.virtual void vf( )=0;D.virtual void vf(int){ }
3.7下列描述中,()是抽象类的特性。
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;}
virtual void func2( ) {cout<<”class B func2”<<endl;}
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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<< "水果" <

};

// 派生类1: 香蕉类

class Banana: public Fruit{ public:

void print() {

cout<< "香蕉" <

} };

// 派生类2: 苹果类

class Apple: public Fruit{ public:

void print() {

cout<< "苹果" <

} };

派生类程序代码

// 派生类3: 梨子类

class Pear: public Fruit{ public:

void print() { cout<< "梨子" <

} };

// 派生类4: 桃子类

class Peach: public Fruit{ public:

void print() { cout<< "桃子" <

} };

#include 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<< "水果" <

}

};

7.小结

✓虚函数是多态的一种实现形式;

✓作用是实现函数的覆盖;

✓写法是将virtual加在函数之前;

✓今后在类的继承当中的基类尽量多使用虚函数。

相关文档
最新文档