实验6多态性与虚函数
c++多态性与虚函数习题答案
多态性与虚函数1.概念填空题1.1 C++支持两种多态性,分别是编译时和运行时。
1.2在编译时就确定的函数调用称为静态联编,它通过使用函数重载,模板等实现。
1.3在运行时才确定的函数调用称为动态联编,它通过虚函数来实现。
1.4虚函数的声明方法是在函数原型前加上关键字virtual。
在基类中含有虚函数,在派生类中的函数没有显式写出virtual关键字,系统依据以下规则判断派生类的这个函数是否是虚函数:该函数是否和基类的虚函数同名;是否与基类的虚函数参数个数相同、类型;是否与基类的虚函数相同返回类型。
如果满足上述3个条件,派生类的函数就是虚函数。
并且该函数覆盖基类的虚函数。
1.5 纯虚函数是一种特别的虚函数,它没有函数的函数体部分,也没有为函数的功能提供实现的代码,它的实现版本必须由派生类给出,因此纯虚函数不能是友元函数。
拥有纯虚函数的类就是抽象类类,这种类不能实例化。
如果纯虚函数没有被重载,则派生类将继承此纯虚函数,即该派生类也是抽象。
3.选择题3.1在C++中,要实现动态联编,必须使用(D)调用虚函数。
A.类名B.派生类指针C.对象名D.基类指针3.2下列函数中,不能说明为虚函数的是(C)。
A.私有成员函数B.公有成员函数C.构造函数D.析构函数3.3在派生类中,重载一个虚函数时,要求函数名、参数的个数、参数的类型、参数的顺序和函数的返回值(A)。
A.相同B.不同C.相容D.部分相同3.4当一个类的某个函数被说明为virtual时,该函数在该类的所有派生类中(A)。
A.都是虚函数B.只有被重新说明时才是虚函数C.只有被重新说明为virtual时才是虚函数D.都不是虚函数3.5(C)是一个在基类中说明的虚函数,它在该基类中没有定义,但要求任何派生类都必须定义自己的版本。
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下列描述中,(D)是抽象类的特性。
【C++面向对象的程序设计】6多态性
虚析构函数
析构函数的作用是对象撤销之后清理现场。 在派生类对象撤销时,一般先调用派生类的 析构函数。再调用基类的析构函数。
然而,当定义的是一个指向基类的指针变量, 使用new运算符建立临时对象时,如果基类 中有析构函数,则在使用delete析构时只会 调用基类的析构函数。
这就需要将基类中的析构函数声明为虚函数。
虚函数的声明与使用
声明虚函数的一般格式如下: virtual 函数原型;
⑴ 必须首先在基类中声明虚函数。 ⑵ 派生类中与基类虚函数原型完全相同的成员函 数,即使在说明时前面没有冠以关键字virtual也 自动成为虚函数。
声明虚函数
⑶ 只有非静态成员函数可以声明为虚函数。 ⑷ 不允许在派生类中定义与基类虚函数名字及参数 特征都相同,仅仅返回类型不同的成员函数。 编译时 出错。 ⑸ 系统把函数名相同但参数特征不同的函数视为不 同的函数。 ⑹ 通过声明虚函数来使用C++提供的多态性机制时, 派生类应该从它的基类公有派生。
构函数等内容。
本章内容
静态联编与动态联编 虚函数的声明与使用 纯虚函数和抽象类 虚析构函数
Hale Waihona Puke 静态联编与动态联编所谓联编(tinding),就是使一个计算机程序的不同部 分彼此关联的过程。
静态联编在编译阶段完成,因为所有联编过程都在程 序开始运行之前完成,因此静态联编也叫先前联编或早期 联编。
另一种情况编译程序在编译时并不确切知道应把发送 到对象的消息和实现消息的哪段具体代码联编在一起,而 是在运行时才能把函数调用与函数体联系在一起,则称为 动态联编。
动态联编的实现
C ++语言中的动态联编是通过使用虚函数表 (Virtual Function Table)来实现的,虚函数表也称 为v-表。
实验6 多态性与虚函数
实验6 多态性与虚函数
实验6 多态性与虚函数
6.1 实验目的
1 .理解多态性的概念;
2 .掌握虚函数的作用及使用方法;
3 .了解静态关联和动态关联的概念和用法;
4 .了解纯虚函数和抽象类的概念和用法。
6.2 实验内容
程序设计部分
1 、定义平面图形的抽象基类figure,然后派生出四种几何图形是:三角形
/Triangle、矩形/Rectangle、正方形/Square和圆/Circle,利用基类指针和虚函数的多
态性来计算四种几何图形的面积和周长,这几何图形的参数通过构造函数来设置。
2 、定义立体图形的抽象基类shape,然后派生出:球、圆柱和圆锥,利用基类的引
用和虚函数的多态性来计算它们的表面积和体积。
本课程复习要点: 1、有关概念和知识点
变量的作用域和生存期,引用,常量,内联函数,函数重载,动态内存分配,输入/
输出流;类与对象,构造函数,拷贝构造函数,析构函数,友元;类成员的访问控制属性,this指针,静态成员,成员对象;派生/继承,多继承,构造函数调用顺序,虚基类;多态性与虚函数,抽象基类,运算符重载。
2、几个较完善的C++教学参考电子文档
3、练习:《C++程序设计基础与实践教程》习题解答、每个实验中的题目
感谢您的阅读,祝您生活愉快。
实验6 多态性与虚函数
实验6 多态性与虚函数一.实验目的1.了解多态的概念;2.了解静态联编和动态联编的概念;3.掌握动态联编的条件;4.了解虚函数的用途及使用方法。
二源程序#include<iostream>using namespace std;class Shape{public:virtual double area()const=0;virtual void display()=0;};class TwoDimShape:public Shape{};class ThreeDimShape:public Shape{};class Circle:public TwoDimShape{public:Circle(double r){R=r;}double area()const{return 3.14*3.14*R;}void display(){cout<<"圆的面积为:"<<area()<<endl;}private:double R;};class Cube:public ThreeDimShape{public:Cube(double l){L=l;}double area()const{return 6*L*L;}void display(){cout<<"立方体的表面积为:"<<area()<<endl;} private:double L;};int main(){int i;Circle Ci1(5.2);Cube Cu1(3.3);Shape *S1[2]={&Ci1,&Cu1};for(i=0;i<2;i++){S1[i]->area();S1[i]->display();}return 0;}三.编程思想圆和立方体不属于同一类,这两类的参数不同计算方法不同,但是所求的都是面积输出的也都是面积这一个相同的成员函数。
实验六、多态性与虚函数
实验六、多态性与虚函数09计算机1 白杨0929210028在掌握继承与派生的基础上,进一步理解多态性与虚函数的关系,实现运行时的多态性。
(1)通过定义形状类Shape,并派生出各类具体形状,标准模板库完成TOJ中的2034题:面积排序(2)分析该题目中所涉及的抽象类、虚函数等概念;(3)分析该题目特别要注意的地方。
Toj 2034#include<iostream>#include<vector>#include<string>#include<cmath>#include<iomanip>#include<algorithm>using namespace std;#define PI 3.1415926class Point{private:double x, y;public:Point() {}Point(double _x, double _y) : x(_x), y(_y) {}Point(const Point& P) {x = P.x; y = P.y;}~Point() {}void SetPoint() {cin>>x>>y;}friend class Triangle;friend class Rectangle;friend class Circle;};class Shape{public:string Sname;Shape() {}Shape(string name) {Sname = name;}Shape(const Shape& S) {Sname = S.Sname;}~Shape() {}virtual void Set(string name) {cin>>Sname;}virtual double Area() {return 0.0;}void Print() {cout.setf(ios::fixed); cout<<Sname<<" "<<setprecision(3)<<Area()<<endl;}};class Triangle : public Shape{private:Point p1, p2, p3;public:Triangle() {}Triangle(string name, Point _p1, Point _p2, Point _p3) : Shape(name), p1(_p1), p2(_p2), p3(_p3) {}Triangle(const Triangle& T) {Sname = T.Sname; p1 = T.p1; p2 = T.p2; p3 = T.p3;}~Triangle() {}void Set(string name) {Sname = name; p1.SetPoint(); p2.SetPoint(); p3.SetPoint();}double Area() {return fabs(p1.x*p2.y-p2.x*p1.y+p2.x*p3.y-p3.x*p2.y+p3.x*p1.y-p1.x*p3.y)*0.5;}};class Rectangle : public Shape{private:Point p1, p2;public:Rectangle() {}Rectangle(string name, Point _p1, Point _p2) : Shape(name), p1(_p1), p2(_p2) {}Rectangle(const Rectangle& R) {Sname = R.Sname; p1 = R.p1; p2 = R.p2;}~Rectangle() {}void Set(string name) {Sname = name; p1.SetPoint(); p2.SetPoint();}double Area() {return fabs(p1.x-p2.x)*fabs(p1.y-p2.y);}};class Circle : public Shape{private:Point center;double r;public:Circle() {}Circle(string name, Point _center, double _r) : Shape(name), center(_center), r(_r) {}Circle(const Circle& C) {Sname = C.Sname; center = C.center; r = C.r;}~Circle() {}void Set(string name) {Sname = name; center.SetPoint(); cin>>r;}double Area() {return PI*r*r;}};bool cmp(Shape* s1, Shape* s2){if(s1->Area() == s2->Area())return s1->Sname < s2->Sname;return s1->Area() > s2->Area();}int main(){vector<Shape *> s;Shape *tmp;string str;int t1(0), r1(0), c1(0);while(cin>>str){if(str=="triangle"){tmp = new Triangle;tmp->Set(str += ++t1+'0');}else if(str=="rectangle"){tmp = new Rectangle;tmp->Set(str += ++r1+'0');}else if(str=="circle"){tmp = new Circle;tmp->Set(str += ++c1+'0');}s.push_back(tmp);}sort(s.begin(),s.end(),cmp);vector<Shape *>::iterator i;for(i=s.begin();i!=s.end();i++)(*i)->Print();return 0;}总结:通过指向派生类对象的基类指针访问函数成员时:非虚函数由指针类型决定调用的版本虚函数由指针指向的实际对象决定调用的版本。
多态性与虚函数实验报告
cout<<"三角形的底为:"<<width<<"高为:"<<height <<"面积为:"<<width*height/2<<endl;
}
private:
float width,height;
};
class Circle:public Base
{
public:
Circle(float r){radius = r;}
p= &obj1;
p->area();
p=&obj2;
p->area();
return 0;
}
【实验结果与数据处理】
【实验结论】
分析:用虚函数实现多态。
【实验器材】
微型计算机、Visual C++ 6.0集成软件平台
【实验步骤】
1.编辑源程序。
2.对源程序进行编译并调试程序。
3.连接并运行程序。
4.检查输出结果是否正确。程序设计如下:
#include<iostream.h>
const float PI = 3.14;
class Base
多态性与虚函数实验报告
实验题目
多态性与虚函数
日期
班级
组别
姓名
类型
【实验目的】
1.理解多态性的概念。
2.了解编译时的多态和运行时的多态。
3.掌握虚函数的定义及实现,掌握虚析构函数的使用方法。
4.了解纯虚函数和抽象类的关系及用法。
【实验原理】
设计一个基类Base,其作用是计算一个图形的面积,它只有一个公有的函数成员虚函数area。再从Base类公有派生一个三角形类Triangle和一个圆类Circle,在类Triangle和类Circle中分别定义自己的area函数,用于计算各自的面积。在主函数中设计一个Base类的对象指针,分别指向类Triangle和类Circle的对象,调用各自的area函数显示相应对象的面积。
多态性与虚函数实验报告
多态性与虚函数实验报告实验目的:通过实验掌握多态性和虚函数的概念及使用方法,理解多态性实现原理和虚函数的应用场景。
实验原理:1.多态性:多态性是指在面向对象编程中,同一种行为或者方法可以具有多种不同形态的能力。
它是面向对象编程的核心特性之一,能够提供更加灵活和可扩展的代码结构。
多态性主要通过继承和接口来实现。
继承是指子类可以重写父类的方法,实现自己的特定行为;接口是一种约束,定义了类应该实现的方法和属性。
2.虚函数:虚函数是在基类中声明的函数,它可以在派生类中被重新定义,以实现多态性。
在类的成员函数前面加上virtual关键字,就可以将它定义为虚函数。
当使用基类指针或引用调用虚函数时,实际调用的是派生类的重写函数。
实验步骤:1. 创建一个基类Shape,包含两个成员变量color和area,并声明一个虚函数printArea(用于打印面积。
2. 创建三个派生类Circle、Rectangle和Triangle,分别继承Shape类,并重写printArea(函数。
3. 在主函数中,通过基类指针分别指向派生类的对象,并调用printArea(函数,观察多态性的效果。
实验结果与分析:在实验中,通过创建Shape类和派生类Circle、Rectangle和Triangle,可以实现对不同形状图形面积的计算和打印。
当使用基类指针调用printArea(函数时,实际调用的是派生类的重写函数,而不是基类的函数。
这就是多态性的实现,通过基类指针或引用,能够调用不同对象的同名函数,实现了对不同对象的统一操作。
通过实验1.提高代码的可扩展性和灵活性:通过多态性,可以将一类具有相似功能的对象统一管理,节省了代码的重复编写和修改成本,增强了代码的可扩展性和灵活性。
2.简化代码结构:通过虚函数,可以将各个派生类的不同行为统一命名为同一个函数,简化了代码结构,提高了代码的可读性和维护性。
3.支持动态绑定:通过运行时的动态绑定,可以根据对象的实际类型来确定调用的函数,实现了动态绑定和多态性。
《面向对象程序设计》实验指导书 (1-6个实验,含参考代码)要点
面向对象程序设计实验指导书(适用:电子信息11级)彭召意陶立新编写计算机与通信学院2014.9目录实验一 C++基础的应用 (1)实验二类和对象的应用 (3)实验三类的构造函数、析构函数的应用 (4)实验四友员和运算符重载 (5)实验五类的继承与派生 (6)实验六类的多态性与虚函数 (7)附录:各实验的程序代码 (8)实验一 C++基础的应用(实验课时:2 实验性质:设计)实验名称: C++基础的应用实验目的: (1)进一步学习VC++6.0开发环境及程序调试方法。
(2)练习C++函数的定义及使用;(3)练习C++数组的定义及使用;(4)练习C++指针的定义及使用;(5)练习C++结构体的定义及使用;(6)练习多文件的程序的编译和运行方法;实验设备:(1)硬件:个人微机(配置不低于:CPU为P4,主频1.6G,内存256MB,硬盘40GB);(2)软件:操作系统为WindowsXP(或2000、server2003等),工具软件为Visual C++6.0。
实验内容: (1)熟悉Visual C++6.0编译系统的常用功能,特别是debug调试功能;(2)编程1:编写一个程序c1.cpp,用来求2个或3个整数的最大数。
要求:用重载函数的方法来求最大数;函数原型:int max( int a, int b) 和int max( int a, int b,int c)。
(3)编程2:编写一个程序c2.cpp,求:a!+ b! + c!的值。
要求:使用递归函数。
主程序和函数分开到两个源程序文件中,分别进行编译后,再运行;(4)编程3:有一个3*4的矩阵,要求编程求出其中值最大的那个元素的值,以及其所在的行号和列号;(5)编程4:建立一个动态链表并进行输出和删除管理。
链表的每个节点为学生信息,包括:学号,姓名,性别,下一学生信息的指针。
程序的工作:(a)建立三个学生信息的节点,然后顺序输出该三个学生信息;(b)删除中间的节点,再顺序输出学生信息。
多态性和虚函数 实验报告
淮海工学院计算机科学系实验报告书课程名:《 C++程序设计(二)》题目:多态性和虚函数班级:学号:姓名:1、实验内容或题目(1)声明二维坐标类作为基类派生圆的类,把派生类圆作为基类,派生圆柱体类。
其中,基类二维坐标类有成员数据:x、y坐标值;有成员函数:构造函数实现对基类成员数据的初始化、输出的成员函数,要求输出坐标位置。
派生类圆类有新增成员数据:半径(R);有成员函数:构造函数实现对成员数据的初始化、计算圆面积的成员函数、输出半径的成员函数。
派生圆柱体类新增数据有高(H);新增成员函数有:构造函数、计算圆柱体体积的函数和输出所有成员的函数。
请完成程序代码的编写、调试。
(2)教材393页7-8题。
(3)教材416页1、4、5题。
2、实验目的与要求(1)理解继承与派生的概念(2)掌握通过继承派生出一个新的类的方法(3)了解多态性的概念(4)了解虚函数的作用与使用方法3、实验步骤与源程序⑴实验步骤先定义一个基类point,及其成员函数,然后以public的继承方式定义子类circle,再定义一个派生类cylinder,最后在main主函数中定义类对象,调用函数实现其功能。
先定义一个基类A及其重载的构造函数,然后以Public派生出子类B,再定义其构造函数,最后在main主函数中定义类对象,调用成员函数实现其功能。
⑵源代码1.#include <iostream.h>class Point{public:Point(float=0,float=0);void setPoint(float,float);float getX() const {return x;}float getY() const {return y;}friend ostream & operator<<(ostream &,const Point &); protected:float x,y;};Point::Point(float a,float b){x=a;y=b;}void Point::setPoint(float a,float b){x=a;y=b;}ostream & operator<<(ostream &output,const Point &p){cout<<"["<<p.x<<","<<p.y<<"]"<<endl;return output;}class Circle:public Point{public:Circle(float x=0,float y=0,float r=0);void setRadius(float);float getRadius() const;float area () const;friend ostream &operator<<(ostream &,const Circle &); protected:float radius;};Circle::Circle(float a,float b,float r):Point(a,b),radius(r){}void Circle::setRadius(float r){radius=r;}float Circle::getRadius() const {return radius;}float Circle::area() const{return 3.14159*radius*radius;}ostream &operator<<(ostream &output,const Circle &c){cout<<"Center=["<<c.x<<","<<c.y<<"], r="<<c.radius<<", area="<<c.area()<<endl;return output;}class Cylinder:public Circle{public:Cylinder (float x=0,float y=0,float r=0,float h=0);void setHeight(float);float getHeight() const;float area() const;float volume() const;friend ostream& operator<<(ostream&,const Cylinder&);protected:float height;};Cylinder::Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h){}void Cylinder::setHeight(float h){height=h;}float Cylinder::getHeight() const {return height;}float Cylinder::area() const{return 2*Circle::area()+2*3.14159*radius*height;}float Cylinder::volume() const{return Circle::area()*height;}ostream &operator<<(ostream &output,const Cylinder& cy){cout<<"Center=["<<cy.x<<","<<cy.y<<"], r="<<cy.radius<<", h="<<cy.height <<"\narea="<<cy.area()<<", volume="<<cy.volume()<<endl;return output;}int main(){Cylinder cy1(3.5,6.4,5.2,10);cout<<"\noriginal cylinder:\nx="<<cy1.getX()<<", y="<<cy1.getY()<<", r=" <<cy1.getRadius()<<", h="<<cy1.getHeight()<<"\narea="<<cy1.area()<<", volume="<<cy1.volume()<<endl;cy1.setHeight(15);cy1.setRadius(7.5);cy1.setPoint(5,5);cout<<"\nnew cylinder:\n"<<cy1;Point &pRef=cy1;cout<<"\npRef as a point:"<<pRef;Circle &cRef=cy1;cout<<"\ncRef as a Circle:"<<cRef;return 0;}2.(1)#include <iostream>using namespace std;class A{public:A(){a=0;b=0;}A(int i){a=i;b=0;}A(int i,int j){a=i;b=j;}void display(){cout<<"a="<<a<<" b="<<b;} private:int a;int b;};class B : public A{public:B(){c=0;}B(int i):A(i){c=0;}B(int i,int j):A(i,j){c=0;}B(int i,int j,int k):A(i,j){c=k;}void display1(){display();cout<<" c="<<c<<endl;}private:int c;};int main(){B b1;B b2(1);B b3(1,3);B b4(1,3,5);b1.display1();b2.display1();b3.display1();b4.display1();return 0;}(2)#include <iostream>using namespace std;class A{public:A(){cout<<"constructing A "<<endl;} ~A(){cout<<"destructing A "<<endl;} };class B : public A{public:B(){cout<<"constructing B "<<endl;} ~B(){cout<<"destructing B "<<endl;} };class C : public B{public:C(){cout<<"constructing C "<<endl;}~C(){cout<<"destructing C "<<endl;}};int main(){C c1;return 0;}3.(1)//Point.hclass Point{public:Point(float=0,float=0);void setPoint(float,float);float getX() const {return x;}float getY() const {return y;}friend ostream & operator<<(ostream &,const Point &); protected:float x,y;}//Point.cppPoint::Point(float a,float b){x=a;y=b;}void Point::setPoint(float a,float b){x=a;y=b;}ostream & operator<<(ostream &output,const Point &p){output<<"["<<p.x<<","<<p.y<<"]"<<endl;return output;}//Circle.h#include "point.h"class Circle:public Point{public:Circle(float x=0,float y=0,float r=0);void setRadius(float);float getRadius() const;float area () const;friend ostream &operator<<(ostream &,const Circle &);protected:float radius;};//Circle.cppCircle::Circle(float a,float b,float r):Point(a,b),radius(r){}void Circle::setRadius(float r){radius=r;}float Circle::getRadius() const {return radius;}float Circle::area() const{return 3.14159*radius*radius;}ostream &operator<<(ostream &output,const Circle &c){output<<"Center=["<<c.x<<","<<c.y<<"], r="<<c.radius<<", area="<<c.area()<<endl;return output;}//Cylinder.h#include "circle.h"class Cylinder:public Circle{public:Cylinder (float x=0,float y=0,float r=0,float h=0);void setHeight(float);float getHeight() const;float area() const;float volume() const;friend ostream& operator<<(ostream&,const Cylinder&);protected:float height;};//Cylinder.cppCylinder::Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h){}void Cylinder::setHeight(float h){height=h;}float Cylinder::getHeight() const {return height;}float Cylinder::area() const{ return 2*Circle::area()+2*3.14159*radius*height;}float Cylinder::volume() const{return Circle::area()*height;}ostream &operator<<(ostream &output,const Cylinder& cy){output<<"Center=["<<cy.x<<","<<cy.y<<"], r="<<cy.radius<<", h="<<cy.height<<"\narea="<<cy.area()<<", volume="<<cy.volume()<<endl;return output;}//main.cpp#include <iostream.h>#include "cylinder.h"#include "point.cpp"#include "circle.cpp"#include "cylinder.cpp"int main(){Cylinder cy1(3.5,6.4,5.2,10);cout<<"\noriginal cylinder:\nx="<<cy1.getX()<<", y="<<cy1.getY()<<", r=" <<cy1.getRadius()<<", h="<<cy1.getHeight()<<"\narea="<<cy1.area()<<", volume="<<cy1.volume()<<endl;cy1.setHeight(15);cy1.setRadius(7.5);cy1.setPoint(5,5);cout<<"\nnew cylinder:\n"<<cy1;Point &pRef=cy1;cout<<"\npRef as a point:"<<pRef;Circle &cRef=cy1;cout<<"\ncRef as a Circle:"<<cRef;return 0;}(2)#include <iostream>using namespace std;class Shape{public:virtual double area() const =0;class Circle:public Shape{public:Circle(double r):radius(r){} virtual double area() const {return 3.14159*radius*radius;}; protected:double radius;};class Rectangle:public Shape{public:Rectangle(double w,double h):width(w),height(h){} virtual double area() const {return width*height;} protected:double width,height; };class Triangle:public Shape{public:Triangle(double w,double h):width(w),height(h){} virtual double area() const {return 0.5*width*height;} protected:double width,height; };void printArea(const Shape &s)cout<<s.area()<<endl;} int main(){Circle circle(12.6);cout<<"area of circle =";printArea(circle);Rectangle rectangle(4.5,8.4);cout<<"area of rectangle =";printArea(rectangle);Triangle triangle(4.5,8.4);cout<<"area of triangle =";printArea(triangle);return 0;}(3)#include <iostream>using namespace std;class Shape{public:virtual double area() const =0;};class Circle:public Shape{public:Circle(double r):radius(r){}virtual double area() const {return 3.14159*radius*radius;}; protected:double radius;class Square:public Shape{public:Square(double s):side(s){}virtual double area() const {return side*side;}protected:double side;};class Rectangle:public Shape{public:Rectangle(double w,double h):width(w),height(h){}virtual double area() const {return width*height;}protected:double width,height; };class Trapezoid:public Shape{public:Trapezoid(double t,double b,double h):top(t),bottom(t),height(h){} virtual double area() const {return 0.5*(top+bottom)*height;} protected:double top,bottom,height;};class Triangle:public Shapepublic:Triangle(double w,double h):width(w),height(h){}virtual double area() const {return 0.5*width*height;} protected:double width,height;};int main(){Circle circle(12.6);Square square(3.5);Rectangle rectangle(4.5,8.4);Trapezoid trapezoid(2.0,4.5,3.2);Triangle triangle(4.5,8.4);Shape *pt[5]={&circle,&square,&rectangle,&trapezoid,&triangle};double areas=0.0;for(int i=0;i<5;i++){areas=areas+pt[i]->area();}cout<<"totol of all areas="<<areas<<endl;return 0;}4、测试数据与实验结果(可以抓图粘贴)5、结果分析与实验体会继承时,子类对基类的访问属性,基类的私有成员无论以何种方式继承在子类中都是不可访问的,唯有调用基类中的成员函数方可访问其私有变量。
多态性和虚函数
void main() { Grandam *ptr; Grandam g; Mother m; Daughter d; ptr=&g; ptr->introduce_self();//调用基类 调用基类Grandam的introduce_self() 调用基类 的 ptr=&m; ptr->introduce_self();// 调用派生类 调用派生类Mother的introduce_self() 的 ptr=&d; ptr->introduce_self(); //调用派生类 调用派生类 // Daughter的introduce_self() 的 }
6.3 纯虚函数和抽象类
6.3.1 纯虚函数 纯虚函数是一个在基类中说明的虚 函数, 它在该基类中没有定义, 函数 , 它在该基类中没有定义 , 但要求 在它的派生类中必须定义自己的版本, 在它的派生类中必须定义自己的版本 , 或重新说明为纯虚函数。 或重新说明为纯虚函数。 纯虚函数的定义形式如下: 纯虚函数的定义形式如下 virtual 函数类型 函数名 参数表 函数名(参数表 参数表)=0;
6.2.4虚函数与重载函数的关系 虚函数与重载函数的关系
在一个派生类中重新定义基类的虚函数是函数重载的另 一种形式,但它不同于一般的函数重载。 一种形式,但它不同于一般的函数重载。 普通的函数重载时, ◆ 普通的函数重载时 , 其函数的参数或参数类型必须有 所不同,函数的返回类型也可以不同。 所不同,函数的返回类型也可以不同。 当重载一个虚函数时, ◆ 当重载一个虚函数时 , 也就是说在派生类中重新定义 虚函数时,要求函数名、返回类型、参数个数、 虚函数时,要求函数名、返回类型、参数个数、参数的类型 和顺序与基类中的虚函数原型完全相同。 和顺序与基类中的虚函数原型完全相同。 如果仅仅返回类型不同,其余均相同, ◆ 如果仅仅返回类型不同 , 其余均相同 , 系统会给出错 误信息; 误信息 若仅仅函数名相同,而参数的个数、类型或顺序不同, ◆若仅仅函数名相同,而参数的个数、类型或顺序不同, 系统将它作为普通的函数重载,这时将丢失虚函数的特性。 系统将它作为普通的函数重载,这时将丢失虚函数的特性。
c讲稿Chapter6多态性与虚函数
数。
PPT文档演模板
c讲稿Chapter6多态性与虚函数
6.2 虚函数
6.2.2 虚函数
• (六)在什么情况下使用虚函数 • 1、成员函数所在的类会成为基类 • 2、派生类中需要对该成员函数进行修改 • 3、派生类中通过指针或引用调用该成员函数
态多态性。 2、动态多态性 q 指在程序运行过程中才动态确定函数的调用。 q 实现方式——虚函数 q 又称运行时的多态性
PPT文档演模板
c讲稿Chapter6多态性与虚函数
例题
q 例6.1 q 例6.2
PPT文档演模板
c讲稿Chapter6多态性与虚函数
本章内容
6.1 多态性的概念
6.2 虚函数
PPT文档演模板
c讲稿Chapter6多态性与虚函数
6.3 纯虚函数与抽象类
q 在C++中的类族中•几,何为图了形提供一个统一的访问接 口,往往会提供一个•S具ha有pe抽象意义的基类。
q 例如:
•矩形 Rectangle
•圆 •Circle
•三角形 •Triangle
•长方 体
•Box
PPT文档演模板
PPT文档演模板
c讲稿Chapter6多态性与虚函数
//声明Circle类 class Circle:public Point {public:
Circle(float x=0,float y=0,float r=0):Point(x,y) { radius = r; }
virtual float area() const{return 3.14*radius*radius;} virtual void shapeName() const {cout<<"Circle:";} protected:
实验6多态性与虚函数
[实验目的]1、了解多态性的概念;2、了解虚函数的用途及使用方法;3、了解纯虚函数和抽象类的概念和用法。
[实验要求]给出以下各实验内容的源程序代码,并把编译、运行过程中出现的问题以及解决方法填入实验报告中,按时上交。
[实验学时]2学时。
[实验内容]1、写一个程序,定义抽象基类Shape,由它派生出3个派生类:Circle(圆形)、Square(正方形)、Rectangle(矩形)。
利用指针、虚函数printArea()分别输出以上三者的面积,3个图形的数据在定义对象时给定。
[源程序]#include<iostream>using namespace std;class Shape{public:virtual float area()const=0;virtual void display()const=0;};class Circle:public Shape{public:Circle(double a):r(a){}virtual float area()const{return 3.14*r*r;}virtual void display()const{cout<<"圆面积"<<area()<<endl;}private:double r;};class Rectangle:public Shape{public:Rectangle(double a,double b):l(a),w(b){}virtual float area()const{return l*w;}virtual void display()const{cout<<"矩形面积"<<area()<<endl;}private:double l;double w;};class Square:public Shape{public:Square(double a):a1(a){}virtual float area()const{return a1*a1;}virtual void display()const{cout<<"正方形面积"<<area()<<endl;}private:double a1;};int main(){Circle c1(5);Rectangle r1(5,8);Square s1(2.5);Shape *p[3]={&c1,&r1,&s1};int i;double m=0.0;for (i=0;i<3;i++){p[i]->display();m=m+p[i]->area();}cout<<"总面积:"<<m<<endl;}2、定义Point(点)类,由Point类派生出Circle(圆)类,再由Circle类派生出Cylinder(圆柱体)类。
c++实验虚函数与多态性
实验九:虚函数与多态性一.实验目的1.掌握动态联编的概念;2.掌握虚函数和纯虚函数的使用方法;3.掌握抽象类的使用。
二.实验内容设计一个计算图形面积的类库。
它的顶层是一个抽象类,并且提供相应的接口函数。
抽象基类Shape,派生出Point类、矩形Rectangle、正方形Square,Point类派生出圆形Circle。
要求:1、每个类有构造函数、析构函数,并有相应的输出语句,如:“正在构造圆形”2、能显示每个类的信息,如:输出“我是圆形”3、能计算面积、周长4、定义一个基类Shape类型的指针,实现动态多态5、动态创建一个圆形对象,赋值给基类Shape类型的指针变量,程序最后delete该指针,保证析构函数的正确调用(提示:虚析构函数)6、在主函数测试。
三.实验操作步骤1.输入源程序,编译、连接直到没有错误2.根据实验步骤,撰写实验报告四、实验要求1.复习教材中和实验相关的内容,提前编好程序。
2.整理上机结果,完成实验报告。
3.注意总结上机体会。
C++程序设计及实训198 #include <iostream>using namespace std;#include<string>class Shape{public:virtual float area()=0;virtual float longth()=0;virtual void show()=0;virtual ~Shape(){}};class Point:public Shape{protected:int x;int y;public:Point(int a=0,int b=0){x=a;y=b;cout<<"is constructing Point"<<endl;}void show(){cout<<"I am point"<<endl;}~Point(){cout<<"is destructing Point"<<endl;}float area(){return 0;}float longth(){实训2:简单C++程序设计return 0;}};class Rectangle:public Point{protected:int l;int w;public:Rectangle(int a=1,int b=1){l=a;w=b;cout<<"is constructing Rectangle"<<endl;}void show(){cout<<"I am Rectangle"<<endl;}float area(){return l*w;}float longth(){return 2*(l+w);}~Rectangle(){cout<<"is destructing Rectangle"<<endl;}};class Square:public Shape{protected:int r;public:Square(int a=1)199C++程序设计及实训200{r=a;cout<<"is constructing Square"<<endl;}void show(){cout<<"I am Square"<<endl;}float area(){return r*r;}float longth(){return 4*r;}~Square(){cout<<"is destructing Square"<<endl;}};class Circle:public Point{protected:int r;public:Circle(int a=1){r=a;cout<<"is constructing Circle"<<endl;}void show(){cout<<"I am Circle"<<endl;}float area(){return r*r*3.14;实训2:简单C++程序设计}float longth(){return 2*3.14*r;}~Circle(){cout<<"is destructing Circle"<<endl;}};int main(){Point a(1,1);Square b(2);Rectangle c(2,1);Shape *p=new Circle ;p->show();delete p;return 0;}{201。
《C++面向对象程序设计》 谭浩强 第六章
C++
先声明基类point类,并调试之; 再声明派生类circle类,调试之; 最后声明cylinder类,调试之。
6- 5
① 先声明基类point
#include <iostream.h> class point //声明类point {public: point (float x=0, float y=0 ); //有默认值的构造函数 void setPoint (float, float); //设置点坐标 float getX ( ) const { return x; } // 读x 值 float getY ( ) const { return y; } // 读y 值 friend ostream & operator << ( ostream &, const point &); protected: float x,y; }; // 下面定义 point类的成员函数 point :: point (float a, float b) // point的构造函数 { x = a; y = b; } void point :: setPoint (float a, float b) { x =a; y = b; } ostream &operator << (ostream &output, const point &p) { // 重载运算符<< output<<“[x=“<<p.x<<“, y=“<<p.y<<“]”<<endl; return output; }
6Hale Waihona Puke 7③ 最后声明cylinder类
C++程序设计基础第6章 虚函数与多态性
6.2.1 虚函数的定义
2. 虚函数的定义 • 虚函数的定义是在基类中进行的 。 • 虚函数的定义语法格式如下:
virtual<函数类型><函数名>(形参表) {
函数体 }
12
6.2.1 虚函数的定义
3. 定义虚函数时,要注意遵循以下规则: 1)只有成员函数才能声明为虚函数,因为虚
函数仅适用于有继承关系的类对象,所以 普通函数不能声明为虚函数。 2)虚函数的声明只能出现在类声明中的函数 原型声明中,而不能出现在成员的函数体 实现上。 3)类的静态成员函数不可以定义为虚函数, 因为静态成员函数不受限于某个对象。
}
7
void main()
{
MaxClass mc(34,67,143,89);
cout<<"计算前两个数中的最大数为:“
<<mc.max(34,67)<<endl;
cout<<"计算前三个数中的最大数为:“
<<mc.max(34,67,143)<<endl;
cout<<"计算四个数中的最大数为:“
运行结果: 张晓强,园林工人 李文卓,生命科学教师
23
6.2.3 虚函数的重载
• 2. 多继承中的虚函数
【例6.8】多继承中使用虚函数例题。
#include <iostream.h>
class base1
//定义基类base1
{
public: virtual void display()
//函数定义为虚函数
运行结果:
(1) : 动物(食草/食肉). (2) : 食草动物 : 羚羊 (3) : 食草动物 : 羚羊 (4) : 食肉动物 : 老虎 (5) : 食肉动物 : 老虎 (6) : 食草动物 : 羚羊 (7) : 食肉动物 : 老虎
多态性与虚函数
1.2.2 运算符重载
运算符重载原理
运算符重载是对已有运算符赋予多重含义,这在 程序设计过程中是十分重要与必要的。在C++语言中, 预先定义的运算符其运算对象只能是基本数据类型, 而不能用于用户定义的类型,如类实例。而在程序 设计中,为了使得程序编写更加简洁,用户希望能 使用运算符来操作类实例,因此产生了运算符重载 模式。运算符重载的过程是将特定的运算表达式转 换为对实现运算符功能的函数调用,而运算对象则 转换为运算符函数的参数。
虚函数可以在派生出的子类中有多个不同实现是虚函
数的重要特性,也就是通过这个特性,用户可以实现多 态性。由此,可以得知,虚函数都是在父类中进行声明 或定义的,而用户声明或定义虚函数的目的就是不确定 该成员函数在派生出的子类中的行为。
1.3.2 虚函数都定义和使用
可以使用如下方式来声明或定义一个虚函数。 virtual 函数类型 函数名称(参数表); 或者 virtual 函数类型 函数名称(参数表) {
指针变量→成员函数名称(参数表); 或
指针变量→成员数据名称; 最后,当类实例使用完毕后,用户使用delete操作,可以将类 实例清除,并归还对应的系统空间,其语法格式如下。
delete 类指针名称;
1.3.3 虚析构函数
指针与虚析构函数
在C++语言的继承模式下,用户可以使用指针来访问派生类,通常情况下 可以有两种方式:利用指向派生类的指针来访问与利用指向父类的指针 来访问。在这两种方式下,析构函数的作用是不同的。
1.3.3 虚析构函数
利用指针访问类实例
在C++语言中,用户可以使用指针或引用的方式来访问类实例。 其具体方式如下:
类名称 *指针名称 = new 类名称; 当类指针定义完毕后,指针指向的类实例中的构造函数将自动 执行,如果用户需要访问该实例中的成员函数或者访问该实例中 的成员数据,可以使用下面的方式:
多态 虚函数
多态虚函数多态和虚函数是面向对象程序设计中非常重要的概念。
下面将对这两个概念进行详细的解释。
一、多态多态是指通过不同的方式来使用相同的实体。
在面向对象程序设计中,多态是指通过同样的方法调用,但是会根据实际调用对象的类型而产生不同的行为。
这种机制被称为动态绑定或者后期绑定。
多态有很多种实现方式,其中最常见的一种是使用虚函数。
其他实现方式包括函数重载、运算符重载和模板函数。
二、虚函数虚函数是指在基类中定义的一个可以被派生类覆盖的函数。
当一个指向派生类对象的基类指针或引用被用来调用虚函数时,根据实际调用对象的类型,会自动选择正确的函数执行。
这种机制被称为动态绑定或者后期绑定。
虚函数的作用是允许派生类重写基类的函数,从而实现多态。
在基类中,将需要被重写的函数声明为虚函数。
在派生类中,如果要重写基类的函数,可以使用override关键字显式地声明。
如果不使用override关键字,派生类中的函数名和参数与基类中的虚函数相同,但是不会被视为虚函数,因为它们没有使用override关键字。
虚函数可以被定义为纯虚函数,纯虚函数是没有函数体的虚函数,它只是一个声明。
派生类必须实现纯虚函数,否则派生类也成为抽象类。
对于虚函数的调用,可以使用基类的指针或引用进行调用。
如果使用基类的指针或引用调用派生类的虚函数,会自动选择正确的函数执行。
总结多态和虚函数是面向对象程序设计中非常重要的概念。
通过多态和虚函数,可以实现代码的灵活性和可复用性。
多态可以通过不同的方式来使用相同的实体,而虚函数可以通过同样的方法调用,但是会根据实际调用对象的类型而产生不同的行为。
在实际的程序设计中,多态和虚函数是必不可少的工具。
除了上面提到的虚函数和多态,还有一些与之相关的重要概念和技术。
1. 抽象类抽象类是只包含纯虚函数的类,也就是说它们没有实现代码,只有声明。
抽象类不能被实例化,而只能被用作派生出其他类的基类。
一个类如果继承了抽象类,必须实现该抽象类中的所有纯虚函数,否则该类仍然无法被实例化并且也是抽象类。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[实验目的]1、了解多态性的概念;2、了解虚函数的用途及使用方法;3、了解纯虚函数和抽象类的概念和用法。
[实验要求]给出以下各实验内容的源程序代码,并把编译、运行过程中出现的问题以及解决方法填入实验报告中,按时上交。
[实验学时]2学时。
[实验内容]1、写一个程序,定义抽象基类Shape,由它派生出3个派生类:Circle(圆形)、Square(正方形)、Rectangle(矩形)。
利用指针、虚函数printArea()分别输出以上三者的面积,3个图形的数据在定义对象时给定。
[源程序]#include<iostream>using namespace std;class Shape{public:virtual float area()const=0;virtual void display()const=0;};class Circle:public Shape{public:Circle(double a):r(a){}virtual float area()const{return 3.14*r*r;}virtual void display()const{cout<<"圆面积"<<area()<<endl;}private:double r;};class Rectangle:public Shape{public:Rectangle(double a,double b):l(a),w(b){}virtual float area()const{return l*w;}virtual void display()const{cout<<"矩形面积"<<area()<<endl;}private:double l;double w;};class Square:public Shape{public:Square(double a):a1(a){}virtual float area()const{return a1*a1;}virtual void display()const{cout<<"正方形面积"<<area()<<endl;}private:double a1;};int main(){Circle c1(5);Rectangle r1(5,8);Square s1(2.5);Shape *p[3]={&c1,&r1,&s1};int i;double m=0.0;for (i=0;i<3;i++){p[i]->display();m=m+p[i]->area();}cout<<"总面积:"<<m<<endl;}2、定义Point(点)类,由Point类派生出Circle(圆)类,再由Circle类派生出Cylinder(圆柱体)类。
将类的定义部分分别作为3个头文件(.h文件),对它们的成员函数的声明部分分别作为3个源文件(.cpp文件),在主函数(.cpp 文件)中用#include命令把它们包含进来,形成一个完整的程序,并上机运行。
[源程序]//Point.hclass Point{public:Point(float a=0,float b=0);void display();protected:float x,y;};//Point.cpp#include<iostream.h>#include"Point.h"Point::Point(float a,float b){x=a;y=b;}void Point::display(){cout<<"Point:"<<endl<<"x="<<x<<endl<<"y="<<y<<endl;}//Circle.hclass Circle:public Point{public:Circle(float x=0,float y=0,float r=0);void display();protected:float radius;};//Circle.cpp#include<iostream.h>#include"Point.h"#include"Circle.h"Circle::Circle(float a,float b,float r):Point(a,b),radius(r){}void Circle::display(){cout<<"Circle:"<<endl;cout<<"x="<<x<<endl;cout<<"y="<<y<<endl;cout<<"radius="<<radius<<endl;cout<<"area="<<radius*radius*3.14<<endl;cout<<endl;}//Cylinder.hclass Cylinder:public Circle{public:Cylinder (float x=0,float y=0,float r=0,float h=0);void display();protected:float height;};//Cylinder.cpp#include<iostream.h>#include"Point.h"#include"Circle.h"#include"Cylinder.h"Cylinder::Cylinder(float a,float b,float r,float h):Circle(a,b,r),height(h){} void Cylinder::display(){cout<<"Cylinder:"<<endl;cout<<"x="<<x<<endl;cout<<"y="<<y<<endl;cout<<"radius="<<radius<<endl;cout<<"height="<<height<<endl;cout<<"area="<<2*radius*radius*3.14+2*3.14*radius*height<<endl;cout<<"volume="<<radius*radius*3.14*height<<endl;cout<<endl;}//Main.cpp#include <iostream.h>#include"Point.h"#include"Circle.h"#include"Cylinder.h"int main(){Point p(2.0,4.0);p.display();Circle c(4.0,5.0,6.0);c.display();Cylinder cy(7.0,8.0,10.0,11.0);cy.display();return 0;}3、要求正方体、球、圆柱的表面积,可以抽象出一个公共的基类Container 为抽象类,在其中定义一个公共的数据成员radius(此数据可以作为正方形的边长、球的半径、圆柱体底面圆半径),以及求表面积的纯虚函数area()。
由此抽象类派生出要描述的三个类,利用基类指针和虚函数,分别计算三种图形的表面积。
[源程序]#include <math.h>#include <iostream.h>#define PI 3.14class Cshape{double radius,height;double area,vol;int name;public:Cshape(double r,double h){radius = r;height = h;name = 3;}Cshape(double r){radius = r;name = 1;}void DisAttr(){if(name == 1)cout<<"球体信息"<<endl;if(name ==2)cout<<"正方形信息"<<endl;cout<<"表面积是:"<<area<<endl;}void DisAttr(int flag){cout<<"圆柱信息"<<endl;cout<<"表面积是:"<<area<<endl;}void Sarea(){area = 4*PI*pow(radius,2);}void Sarea(int cube){area = 6*pow(radius,2);}void Sarea(double cube){name = 3;area = 2*PI*pow(radius,2)+2*PI*radius*height; }};int main(){Cshape yuanqiu(3); yuanqiu.Sarea(); yuanqiu.DisAttr(); Cshape zhengfangxing(3); zhengfangxing.Sarea(1); zhengfangxing.DisAttr(); Cshape yuanzhu(3,4); yuanzhu.Sarea(12.3); yuanzhu.DisAttr(1); return 0;}。