tceic.com
学霸学习网 这下你爽了
赞助商链接
当前位置:首页 >> 计算机软件及应用 >>

实验七 虚函数及应用


实验七 虚函数及应用
一、实验目的
1.理解虚函数与运行时(动态)多态性之间的关系,掌握虚函数的定义及应用; 2.理解纯虚函数与抽象类的概念,掌握抽象类的定义及应用; 3.理解虚析构函数的概念及作用。

二、实验学时
课内实验:2 课时 课外练习:2 课时

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

virtual 返回类型 func_name(参数表)=0; [ { …… } ] 2.抽象类 ⑴ 抽象类的概念 当一个类中定义了一个或多个纯虚函数,则该类称为抽象类。 ⑵ 说明: ① 抽象类中包含没有功能的纯虚函数,用来提供派生类的公共接口函数。因此,抽象 类只能作为其它类的基类,不能定义其对象。 ② 可以定义抽象类的指针或引用,用于指向派生类而实现多态性。 ③ 如果在派生类中未重新定义纯虚函数, 则派生类只是继承了基类的纯虚函数, 这时, 派生类仍是抽象类。 ㈣ 虚析构函数 1.虚析构函数的定义 在析构函数名前加上“virtual” 。即: virtual ~ 类名(void) { …… } 2.说明 当类中需要显式定义析构函数, 而在基类中定义了虚函数时, 应将析构函数定义为虚析 构函数,以实现动态调用析构函数。

四、实验内容
㈠ 验证及认知实验 按要求调试下列程序,并回答相关问题。 程序 1(exp_801.cpp) #include <iostream.h> class Base { int a,b; public : Base(int x,int y) {a=x;b=y;} void show() { cout <<" a="<<a<<" b="<<b; } }; class Derived:public Base { int c; public: Derived(int x,int y,int z):Base(x,y) {c=z;} void show() { Base::show(); cout <<" c="<<c; } };
2

void main() {Base mb(50,50),*mp; Derived md(10,20,30); mp=&mb; mp->show(); cout<<endl; mp=&md; mp->show(); cout<<endl; ((Derived*)mp)->show(); cout<<endl; } 问题: ⑴ 编译运行程序的输出结果为:

⑵ 根据程序的输出结果可知: 执行“mp=&mb; mp->show();”时,调用的是 执行“mp=&md; mp->show();”时,调用的是 执行“((Derived*)mp)->show();”时,调用的是 类的 show() ; 类的 show() ; 类的 show() ; 类的指针。

其中“((Derived*)mp)”是将 Base 类“mp”指针强制转换为

⑶ 在基类“Base”中的成员函数“void show()”改为“virtual void show()” ,再重新 编译运行程序,输出结果为:

⑷ 当执行 “mp=&md; mp->show();” 调用的是 时, 称为 ,实现了 多态性。

类的 show() ; “show()” 函数

程序 2(exp_802.cpp) #include <iostream.h> class Base { public : virtual void show() { cout<<"Base 该类无计算"<<endl; } }; class Derived1:public Base { int a ; public: Derived1(int x) {a=x;}

3

void show() { cout <<"a="<<a<<endl; } }; class Derived2:public Base { int b ; public: Derived2(int x) {b=x;} void show() { cout <<"b="<<b<<endl; } }; void main() {Base mb; Base *mp; Derived1 md1(10); Derived2 md2(20); mp=&mb; mp->show(); mp=&md1; mp->show(); mp=&md2;mp->show(); } 问题: ⑸ 编译运行程序的输出结果为:

⑹ 将“Base”类中的“virtual void show()”改为“virtual void show()=0” ,重新编译程 序会出现 出错原因是 ,其中的“show() ”称为 。 虚函数,该类称为 类,

⑺ 去掉 main()函数中的“Base mb;”及“mp=&mb; mp->show();” ,重新编译运行程序 的输出结果为:

㈡ 知识应用实验 1.分析下列程序,写出程序的输出结果,再上机运行程序验证其正确性,如果不正确, 请认真分析出错原因。 程序 3(exp_803.cpp) #include <iostream.h> class parent {protected :

4

char version; public: parent() {version='A';} virtual void print() {cout <<"\n The parent. version "<<version;} }; class derived1:public parent {private: int info; public: derived1(int number) {info=number; version='1';} void print() {cout<<"\n The derived 1 info:"<<info<<" version "<<version;} }; class derived2:public parent {private: int info; public: derived2(int number) {info=number; } void print() {cout<<"\n The derived 2 info:"<<info<<" version "<<version;} }; 你分析的程序输出结果是: void main() {parent ob,*op; op=&ob; op->print(); derived1 d1(3); op=&d1; op->print(); 程序的实际输出结果是: derived2 d2(15); op=&d2; op->print(); cout <<endl; } 程序 4(exp_804.cpp) #include <iostream.h> class base1 { public: virtual void fun() {cout <<"----base1----"<<endl;}
5

}; class base2 { public: virtual void fun() {cout <<"----base2----"<<endl;} }; class derived:public base1,public base2 { public : void fun() {cout <<"----derived----"<<endl;} }; void main() { base1 ob1,*p1; base2 ob2,*p2; derived ob3; p1=&ob1; p1->fun(); p2=&ob2; p2->fun(); p1=&ob3; p1->fun(); p2=&ob3; p2->fun(); } 程序 5(exp_805.cpp)

你分析的程序输出结果是:

程序的实际输出结果是:

#include <iostream.h> class figure { protected : double x,y; public : figure(double a,double b) {x=a;y=b;} virtual void show_area( ) { cout <<"No area computation defined"; cout <<" for this class.\n"; } }; class triangle:public figure { public: triangle(double a,double b):figure(a,b) {}; void show_area() { cout<<"Triangle with height "<<x; cout<<" and base "<<y<<" has an area of"; cout<<0.5*x*y<<endl;} }; class square:public figure { public :
6

square(double a,double b):figure(a,b) { }; void show_area() { cout <<"Square with dimension "<<x; cout <<" * "<<y<<" has an area of "; cout <<x*y<<endl; } }; class circle:public figure { public: circle(double a):figure(a,a) { }; void show_area() {cout <<"Circle with radius "<<x; cout <<" has an area of "; cout <<x*x*3.141593<<endl; } }; void main() {figure *p; triangle t(10.0,6.0); square s(10.0,6.0); circle c(10.0); p=&t; p->show_area(); p=&s; p->show_area(); p=&c; p->show_area(); }

你分析的程序输出结果是:

程序的实际输出结果是:

2.完善、调试通过下列程序,并按所要求回答问题。 程序 6(exp_806.cpp) //求求圆、圆的内切正方形及外切正方形的面积及周长 #include <iostream.h> #include <math.h> class shape { protected : double r; public: shape(double x) {r=x;} virtual double area()=(1); //定义纯虚函数 virtual double perimeter()=(1); //定义纯虚函数 }; class circle:public shape { public:
7

circle(double x):shape(x) {} double area() {return 3.14*r*r;} double perimeter() {return 2*3.14*r;} }; class in_square:public shape { public: in_square(double x):shape(x) {} double area() {return 2*r*r;} double perimeter() {return 4*sqrt(2)*r;} }; class ex_square:public shape { public: ex_square(double x):shape(x) {} double area() {return 4*r*r;} double perimeter() {return 8*r;} }; void main() { shape *p; circle ob1(5.0); in_square ob2(5.0); ex_square ob3(5); (2); cout <<"Circle :"<<" area="<<p->area(); //输出圆的面积 cout<<" perimeter="<<p->perimeter()<<endl;//输出圆的周长 (3); cout <<"Internal :"<<" area="<<p->area();//输出内切正方形的面积 cout<<" perimeter="<<p->perimeter()<<endl;//输出内切正方形的周长 (4); cout <<"External :"<<" area="<<p->area();//输出外切正方形的面积 cout<<" perimeter="<<p->perimeter()<<endl;//输出外切正方形的周长 }; 问题: 程序中(1)处应改为
8

, (2)处应改为

(3)处应改为 ㈢ 程序设计实验

, (4)处应改为

用动态联编机制处理学生信息: 1.定义抽象类 process:只提供一个纯虚函数 print(); 2.定义 person 类,公有继承 process 类,定义 print()成员函数显示相关信息(用前面已 用过的类) ; 3.定义 student 类,公有继承 person 类,定义 print()成员函数显示相关信息(用前面已 用过的类) ; 4.在 main()函数中,定义 process 指针变量调用 person 对象及 student 对象。 说明:可将 process 类的定义及 person 类的定义放在同一个头文件中;测试程序存放在 exp_807.cpp 中。

五、实验收获与创新
1.自已拟定一个解决实际问题的题目,用动态联编机制编程实现。 2.通过实验七、实验八,谈谈你对 C++语言多态性的认识。

9


赞助商链接
推荐相关:

C++实验7 多态性与虚函数

C++实验7 多态性与虚函数 中南大学c++实验题目中南大学c++实验题目隐藏>> 问题背景:将任意一个平面图形(如长方形、三角形、圆形等)沿其法线方向平移一定长度,它所...


实验七 多态性的应用2(报告)_图文

实验七 多态性的应用2(报告)_计算机软件及应用_IT/计算机_专业资料。实验七 ...在掌握继承与派生关系的基础上,进一步理解虚函数与多态性的关系,实现运行时 实验...


实验六 继承与虚函数

(学院)系: 专姓班学业: 名: 级: 号: 商学院 物流管理 张梦宇 4141040503 414104050316 张有华 2016 年 11 月 7 日 指导教师: 实验六 继承与虚函数 一、...


编程实验七实验报告

实验7 班级:11513 学号:20113051326 姓名:董晶 成绩: 1、实验目的 虚函数与多态性 (1)掌握动态联编的概念; (2)掌握虚函数和纯虚函数的使用方法; (3)掌握...


c++实验七

实验7 班级:11512 虚函数与多态性姓名:刘佳 成绩: 学号:20113051209 1、实验目的 (1)掌握动态联编的概念; (2)掌握虚函数和纯虚函数的使用方法; (3)掌握抽象...


C 实验1-7

《C++程序设计》实验 实验一 实验二 实验三 实验四 实验五 实验六 实验七 ...多态与虚函数程序设计 文件应用综合程序设计 实验一一、实验目的 简单 C++程序...


实验七 八流类库与输入

实验三 数组、指针与字符串... 实验四 继承与派生 实验五 虚函数与多态性 实验十一 MFC的简单消息映...1/2 相关文档推荐 实验7流类库与输入输出 暂无评价 1...


实验七 继承与派生_多态

实验七 继承与派生_多态_计算机软件及应用_IT/计算机_专业资料。姓名: 学号: ...学习利用虚基类解决二义性问题 (4)掌握运算符重载的方法 (5)学习使用虚函数...


实验四虚函数与多态性

实验虚函数与多态性_计算机软件及应用_IT/计算机_专业资料。c++实验 ...7 //8 //9 //10 //11 //12 //13 //14 //15 //16 //17 //18...


实验五、运算符重载

实验5 运算符重载的应用 2页 免费 实验4 运算符重载参考答案... 21页 免费 实验七、模板 4页 5财富值 实验六、多态性与虚函数 4页 5财富值 第六次上机实...

网站首页 | 网站地图
All rights reserved Powered by 学霸学习网 www.tceic.com
copyright ©right 2010-2021。
文档资料库内容来自网络,如有侵犯请联系客服。zhit325@126.com