实验五类的继承与派生
- 格式:doc
- 大小:68.50 KB
- 文档页数:16
C 继承与派生实验报告C 继承与派生实验报告引言:在面向对象的编程中,继承与派生是重要的概念。
通过继承,我们可以从已有的类中派生出新的类,并且可以在新的类中添加额外的属性和方法。
本实验旨在通过实际的编程实践,深入理解C语言中的继承与派生。
实验过程:首先,我们创建了一个基类Animal,其中包含了一个成员变量name和一个成员函数eat。
然后,我们创建了两个派生类Dog和Cat,它们分别继承了Animal类,并且在其中添加了各自特有的成员函数bark和meow。
接着,我们创建了一个对象dog和一个对象cat,并分别调用了它们的成员函数eat、bark 和meow。
实验结果:通过运行程序,我们可以看到dog对象调用了eat和bark函数,而cat对象调用了eat和meow函数。
这说明继承与派生的机制正常工作,派生类可以继承基类的属性和方法,并且可以在派生类中添加新的属性和方法。
实验分析:继承与派生是面向对象编程的重要概念,它可以使得代码的复用性更高,同时也增加了代码的灵活性。
通过继承,派生类可以继承基类的属性和方法,这样可以减少代码的冗余,并且可以在派生类中添加新的功能。
在本实验中,Dog 和Cat类分别继承了Animal类,这样它们就拥有了相同的属性name和方法eat。
然后,通过在派生类中添加新的方法bark和meow,我们可以实现不同的行为。
继承与派生的应用:继承与派生在实际的软件开发中有着广泛的应用。
例如,在一个图形界面程序中,可以定义一个基类Widget,它包含了一些基本的属性和方法,然后可以通过派生类Button和TextBox来创建具体的按钮和文本框。
这样,我们可以通过继承和派生的方式,实现不同的界面元素,并且可以在派生类中添加新的功能,如按钮的点击事件和文本框的输入验证。
继承与派生的注意事项:在使用继承与派生的过程中,我们需要注意一些问题。
首先,派生类可以访问基类的公有成员,但不能访问基类的私有成员。
课程名称:面向对象程序设计实验内容:实验五继承与派生学院:专业班级:姓名:学号:指导教师:实验日期:实验地点:一、实验目的11 1、掌握继承与派生的方法。
2、掌握基类成员在派生类的访问属性。
3、掌握多继承的方法与属性4、掌握虚基类的概念与用法。
二、实验步骤1、定义一个人员类型CPerson,包括数据成员:姓名、编号、性别和构造函数和用于输出的成员函数。
在此基础上派生出学生类CStudent(增加三门成绩,计算总分,平均分)和教师类CTeacher(增加职称),并实现对学生和教师信息输出。
程序代码如下:写出实验步骤、调试记录和实验结果:2、假设图书馆的图书包含书名、编号和作者属性,读者包含姓名和借书证属性,每位读者最多可借5本书,编写程序列出某读者的借书情况,并采用相关数据进行测试。
提示:设计一个类object,从它派生出图书类book和读者类reader,在reader 类中有一个rentbook()成员函数用于借阅图书。
程序代码如下:写出实验步骤、调试记录和实验结果:三、分析与总结(每个步骤10分)1、总结实验所验证的知识点。
在C++中可重用性是通过继承这一机制来实现的。
一个新类从已有的类那里获得其已有特性,这种现象称为类的继承。
从已有的类产生一个新的子类,称为类的派生。
派生类是基类的具体化,而基类则是派生类的抽象。
声明派生类的一般形式为: class 派生类名:[继承方式]基类名 { 派生类新增加的成员 } 。
公用继承基类的公用成员和保护成员在派生类中保持原有访问属性,其私有成员仍为基类私有;私有继承基类的公用成员和保护成员在派生类中成了私有成员。
其私有成员仍为基类私有;受保护的继承基类的公用成员和保护成员在派生类中成了保护成员,其私有成员仍为基类私有。
保护成员的意思是: 不能被外界引用,但可以被派生类的成员引用。
2、写出实验后的学习体会。
通过本次实验,我们基本掌握了继承与派生的方法,知道了基类成员在派生类的访问属性,加深了对多继承和虚基类的属性与用法的理解。
实验目的与要求:1.掌握类的继承与派生关系以及实验方法,理解类的层次结构。
2.掌握派生类构造函数初始化基类成员和对象成员的方法。
3.掌握内联函数和默认函数。
4.掌握赋值兼容原则,掌握派生类的复制构造函数和赋值运算符的定义。
实验过程及内容:1.实践教程实验二十二P81范例:定义一个继承与派生关系的类体系,在派生类中访问基类成员。
①先定义一个点类,包含x,y坐标数据成员,显示函数和计算面积的函数成员;②以点为基类派生一个圆类,增加表示半径的数据成员,重载显示和计算面积的函数;③定义一个线段类,以两个点类对象作数据成员,定义显示、求面积及长度函数,线段类采用聚合方式,因为有两个端点,不能用派生。
编程测试所定义的类体系。
本实验教程中有源码,请自行运行,体会和熟悉继承与派生的基本概念及实现方法,掌握派生类构造函数初始化基类成员和对象成员的方法等。
2. 实践教程P83编程:多层派生练习,由上题Point类和Circle类继续派生出Cylinder类。
要求计算圆柱的底面积、侧面积、全面积和体积。
请编写所有完整的成员函数,并编写主函数进行验证。
数据处理1.(1)(2)j结果报错,原因是派生类中的成员函数不能访问基类中的私有成员。
(3)在Line类中添加两个数据成员。
2. #include <iostream>#include <cmath>using namespace std;#define PI 3.14159class Point{friend class Line;protected:double x, y ;public:Point(){x = 0 ; y = 0 ; }Point(double xv,double yv){ x = xv; y = yv; }double Area(){return 0;}void Show() {cout<<"x="<<x<<' '<<"y="<<y<<endl;}};class Circle :public Point{protected:double radius;public:Circle(){ x = 0; y = 0; radius = 0; }Circle(double xv,double yv,double vv):Point(xv,yv){ //调用基类构造函数radius = vv;}Circle(Circle & cir):Point(cir){ //按赋值兼容规则cir可为Point实参radius=cir.radius;}Circle & operator=(Circle & cir){this->Point::operator=(cir); //在派生类中定义重载的拷贝赋值操作符有固定的标准格式radius=cir.radius;return *this;}double Area(){return PI*radius*radius;}void Show()cout<<"x="<<x<<' '<<"y="<<y<<" radius="<<radius<<endl; //访问基类的数据成员}};class Cylinder:public Circle {double high;public:Cylinder(){ x = 0; y = 0; radius = 0;high=0; }Cylinder(double xv,double yv,double vv,double kv):Circle(xv,yv,vv){ //调用基类构造函数high=kv;}Cylinder(Cylinder & cyl):Circle(cyl){ //按赋值兼容规则cyl可为Cylinder实参high=cyl.high;}Cylinder & operator=(Cylinder & cyl){this->Circle :: operator=(cyl); //在派生类中定义重载的拷贝赋值操作符有固定的标准格式high=cyl.high;return *this;}double ceArea(){return 2*PI*radius*high;}double quArea(){return ceArea()+2* Area();}double volume(){return Area()*high;}void Show(){cout<<"x="<<x<<' '<<"y="<<y<<' '<<"radius="<<radius<<' '<<"high="<<high<<endl; //访问基类的数据成员};class Line{Point start,end; //对象成员public:Line(){} //对象成员初始化Line(double xv1,double yv1,double xv2,double yv2) :start(xv1,yv1),end(xv2,yv2){ }double GetLength() {return sqrt((start.x-end.x)*(start.x-end.x)+(start.y-end.y)*(start.y-end.y));}double Area(){return 0;}void Show(){cout<<"start point:\n";start.Show();cout<<"end point:\n";end.Show();}};int main(){Point pt(0,0);Circle cl1(100,100,10),cl2(cl1),cl3;Cylinder h1(50,50,20,30),h2(h1),h3;Line ln1(0,0,100,100),ln2;cout<<"点面积:"<<pt.Area()<<endl;pt.Show();cout<<"cl1圆面积:"<<cl1.Area()<<endl;cl1.Show();cout<<"cl2圆面积:"<<cl2.Area()<<endl;cl2.Show();cl3=cl1;cout<<"cl3圆面积:"<<cl3.Area()<<endl;cl3.Show();cout<<"h1底面积:"<<h1.Area()<<endl;cout<<"h1侧面积:"<<h1.ceArea()<<endl;cout<<"h1全面积:"<<h1.quArea()<<endl;cout<<"h1体积:"<<h1.volume()<<endl;h1.Show();cout<<"h2底面积:"<<h2.Area()<<endl;cout<<"h2侧面积:"<<h2.ceArea()<<endl;cout<<"h2全面积:"<<h2.quArea()<<endl;cout<<"h2体积:"<<h2.volume()<<endl;h2.Show();h3=h1;cout<<"h3底面积:"<<h3.Area()<<endl;cout<<"h3侧面积:"<<h3.ceArea()<<endl;cout<<"h3全面积:"<<h3.quArea()<<endl;cout<<"h3体积:"<<h3.volume()<<endl;h3.Show();cout<<"线面积:"<<ln1. Area()<<'\t'<<"线长度:"<<ln1. GetLength()<<endl;ln1.Show();ln2.Show();return 0;}实验结论:通过这次实验,我对类的继承和派生,派生类构造函数初始化基类成员和对象成员的方法,以及赋值兼容原则有了更深的理解。
实验项目:继承与派生实验目的:1.学习定义和使用类的继承关系,定义派生类2.熟悉不同继承方式下对基类成员的访问控制实验任务:1.定义一个基类Animal,有私有整形成员变量age,构造其派生类dog,在其成员函数SetAge(int n)中直接给age赋值,看看会有什么问题,把age改为公有成员变量,还会有问题吗2.定义一个基类BaseClass,有整形成员变量Number,构造其派生类,观察其构造函数和析构函数的执行情况。
3.定义一个车类(vehicle)基类,有MaxSpeed、Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类、汽车(motorcar)类。
自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(Seatnum)等属性。
,在继承和过程中,注意把vehicle设置为虚基类。
如果不把vehicle设置为虚基类,会有什么问题变成试试看。
实验步骤:1.编写程序定义Animal,成员变量age定义为私有的。
构造其派生类dog,在其成员函数SetAge(int n)中直接对age赋值时,会出现错误提示:程序名lab5_1.cpp2.编写程序定义一个基类BaseClass,构造其派生类DerivedClass,在构造函数和析构函数中用cout输出提示信息,观察构造函数和析构函数的执行情况。
程序名lab5_2.cpp3.用debug功能跟踪程序lab5_2.cpp的执行过程,观察基类和派生类的构造函数和析构函数的的执行过程。
4.编写程序定义车类(vehicle),由此派生出自行车(bicycle)类、汽车(motorcar),把vehicle设置为虚基类。
再从bicycle和motorcar派生出摩托车(motorcycle)类,在main()函数中测试这个类。
程序名lab5_3.cpp。
编译成功后把vehicle设置成非虚基类,在编译一次,此时系统报错,无法编译成功。
上海电力学院实验报告课程名称Visual C++ 实验项目类和对象、继承和派生姓名储昊学号20132234 班级2013112 专业通信工程同组人姓名指导教师姓名实验日期实验内容程序Ex_Class:定义一个人员类CPerson,包括的数据成员有姓名、编号、性别和用于输入/输出的成员函数。
在此基础上派生出学生类Cstudent(增加成绩)和教师类Cteacher(增加教龄),并实现对学生和教师信息的输入/输出。
编写一个完整的测试程序,并将Ex_Class 所有的类定义保存在Ex_Class.h中,将类的成员函数实现代码保存在Ex_Class.cpp中。
实验准备和说明(1)在学习完第2章的“继承和派生”内容之后进行本次试验。
(2)编写本次上机所需要的程序。
实验步骤1.创建工作文件夹打开计算机,在“D:\Visual C++程序\LiMing\5”文件夹中创建一个新的子文件夹“5”。
2.输入程序Ex_Class.h(1)启动Visual C++6.0。
(2)单击标准工具栏上的“New Test File”按钮,在新打开的文档窗口中输入下列程序代码:#include<iostream.h>#include<string.h>class CPerson{public:CPerson(){strcpy(pName,"");strcpy(pID,"");}CPerson(char*name,char*id,bool isman=1){Input(name,id,isman);}void Input(char*name,char*id,bool isman) {setName(name);setID(id);setSex(isman);}void Output(){cout<<"姓名:"<<pName<<endl;cout<<"编号:"<<pID<<endl;char*str=bMan?"男":"女";cout<<"性别:"<<str<<endl;}public://姓名属性操作char*getName()const{return(char*)pName;}void setName(char*name){int n=strlen(name);strncpy(pName,name,n);pName[n]='\0';}//编号属性操作char*getID()const{return(char*)pID;}void setID(char*id){int n=strlen(id);strncpy(pID,id,n);pID[n]='\0';}//性别属性操作bool getSex(){return bMan;}void setSex(bool isman){bMan=isman;}private:char pName[20];char pID[20];bool bMan;};class CStudent:public CPerson{public:CStudent(char*name,char*id,bool isman=1);~CStudent(){}void InputScore(double score1,double score2,double score3);void Print();CPerson student;private:double dbScore[3];};class CTeacher:public CPerson{public:CTeacher(char*name,char*id,bool isman=1,int years=10);~CTeacher(){}void Print();private:int nTeachYears;};(3)单击标准工具栏上的“Save”按钮,弹出“保存为”文件对话框。
实验五继承与派生一、实验目的( 1 )熟练掌握类的继承,能够定义和使用类的继承关系。
( 2 )掌握派生类的声明与实现方法。
( 3 )掌握类构造函数的初始化列表与作用域分辨符的使用方法。
二、实验工具与准备工作在开始实验前,应回顾或复习相关内容。
需要一台主算机,其中安装有VisualC + + 6 .0 、VisualC + + 2005 、VisualC + + 2005 ExpreSS 、Dev 一C + +或MinGW Developer Studio 等集成开发环境软件。
三、实验内容完成设计性实验项目8.7 创建一个表示雇员信息的employee类,其中包含数据成员name、empNo和salary,分别表示雇员的姓名、编号和月薪。
再从employee类派生出3个类worker、technician和salesman,分别代表普通工人、科研人员、销售人员。
三个类中分别包含数据成员productNum、workHours和monthlysales,分别代表工人每月生产产品的数量、科研人员每月工作的时数和销售人员每月的销售额。
要求各类中都包含成员函数pay,用来计算雇员的月薪,并假定:普通工人的月薪=每月生产的产品数×每件产品的赢利×20%科研人员的月薪=每月的工作时数×每小时工作的酬金销售人员的月薪=月销售额×销售额提成。
#include<iostream>using namespace std;class employee{protected:char name[20];int empNo;float salary;public:employee(char *cp="李强",int no=1001);employee(employee&);void setname(char *cp);void setempNo(int no);void setsalary(float sa);char*getname();int getempNo();float getsalary();void display();employee compsalary(employee *emp);};employee::employee(char *cp,int no){int i=0;while(*cp){name[i]=*cp;i++;cp++;}name[i]='\0';empNo=no;}employee::employee(employee &em) {int i=0;while([i]){name[i]=[i];i++;}name[i]='\0';empNo=em.empNo;salary=em.salary;}void employee::setname(char *cp) {int i=0;while(*cp){name[i]=*cp;i++;cp++;}name[i]='\0';}void employee::setempNo(int no) {empNo=no;}void employee::setsalary(float sa) {salary=sa;}char*employee::getname(){return name;}int employee::getempNo(){return empNo;}float employee::getsalary(){return salary;}void employee::display(){cout<<"工号为"<<empNo<<"的雇员"<<name<<"的月薪为"<<salary<<endl; }employee employee::compsalary(employee *emp){if(this->salary>=emp->salary)return *this;elsereturn *emp;}class worker : public employee{public:worker(char*,int,int);void setproductNum(int n){ productNum=n;}int getproductNum(){ return productNum;}void pay();private:int productNum;static float proper; //每件产品的利润};float worker::proper=30; //假设每件产品的利润为30元worker::worker(char *name,int no,int pronum):employee(name,no){productNum=pronum;}void worker::pay(){salary=productNum*proper*0.2;}class technician : public employee{public:technician(char*,int,float);void sethours(float h){ workHours=h;}float gethours(){ return workHours;}void pay();private:float workHours;static float payperhour; //科研人员每小时工作的酬金};float technician::payperhour=50; //假设科研人员每小时工作的酬金为50元technician::technician(char *name,int no,float hours):employee(name,no){workHours=hours;}void technician::pay(){salary=workHours*payperhour;}class salesman : public employee{public:salesman(char*,int,float);void setmonthlysales(int num){ monthlysales=num;}int getmonthlysales(){ return monthlysales;}void pay();private:float monthlysales;static float percent; //销售人员的销售提成};float salesman::percent=0.6; //假设销售人员的销售提成为60% salesman::salesman(char *name,int n,float sn):employee(name,n){monthlysales=sn;}void salesman::pay(){salary=monthlysales*percent;}void main(){worker w1("王某",1001,1000);technician t1("李某",1002,200);salesman s1("许某",1003,10000);w1.pay();t1.pay();s1.pay();cout<<"工人"<<w1.getname()<<"的月薪为"<<w1.getsalary()<<"元\n";cout<<"科研人员"<<t1.getname()<<"的月薪为"<<t1.getsalary()<<"元\n";cout<<"销售人员"<<s1.getname()<<"的月薪为"<<s1.getsalary()<<"元\n";}8.8 创建一个automobile类表示汽车,其中包含数据成员brand和speed,分别表示汽车的品拍和行驶速度;成员函数run和stop表示行驶和停止。
继承与派生实验报告继承与派生实验报告引言:继承与派生是面向对象编程中的重要概念,通过继承,一个类可以派生出子类,从而实现代码的复用和扩展。
本文将通过实验来探讨继承与派生的概念、原理和应用。
实验目的:1. 理解继承与派生的概念和原理;2. 掌握如何在编程语言中实现继承和派生;3. 熟悉继承与派生的应用场景。
实验步骤:1. 创建父类:首先,我们创建一个名为"Animal"的父类,该类具有属性和方法,例如"age"和"eat()"。
2. 创建子类:接下来,我们创建一个名为"Cat"的子类,该类继承自"Animal"类。
在子类中,我们可以重写父类的方法或添加新的方法。
3. 实例化对象:通过实例化父类和子类的对象,我们可以调用它们的方法和访问它们的属性。
4. 测试继承与派生:我们可以通过调用父类和子类的方法,观察它们的行为是否符合预期。
实验结果:在创建父类"Animal"时,我们定义了一个"age"属性和一个"eat()"方法。
在创建子类"Cat"时,我们继承了父类的属性和方法,并添加了一个新的"meow()"方法。
在实例化父类对象时,我们可以通过调用"eat()"方法来模拟动物进食的行为。
而在实例化子类对象时,我们既可以调用从父类继承而来的"eat()"方法,也可以调用子类特有的"meow()"方法来模拟猫咪的叫声。
通过实验,我们发现继承与派生的优势在于代码的复用和扩展。
我们只需在父类中定义一次通用的属性和方法,然后让不同的子类继承父类,即可实现代码的复用。
同时,子类还可以通过重写父类的方法或添加新的方法,实现代码的扩展和个性化。
讨论与应用:继承与派生不仅仅局限于上述的父类和子类关系,它还可以在多层次的继承结构中发挥作用。
实验5 派生与继承一、实验目的理解继承思想,掌握继承的语法。
⏹体会不同继承方式下派生类对基类成员的访问权限⏹掌握派生类中构造函数和析构函数的定义形式,理解其与基类构造函数和析构函数的关系与调用;⏹掌握派生类与基类同名函数的调用方法⏹理解继承体系中的赋值兼容性原则⏹掌握多继承的语法形式,理解虚继承关系。
二、实验内容1.设计一个学生和教师类,学生数据有编号、姓名、班级和成绩;教师数据有编号、姓名、职称和部门;要求:运用继承的思想实现相关功能:对学生和教师的数据进行输入和显示,类中包括各种构造函数,思考如何在派生类的构造函数中初始化基类的成员。
2.设计球类,用组合及继承包含点,在各个类中添加构造函数和show方法,并能计算球的表面积和体积。
1)按组合关系构造一个球类Ball,包含一个空间中的点(x,y,z)。
2)按继承构造一个球类Sphere,构成三级单继承关系。
3) 按组合和继承关系构造一个非均匀的球体类,其中包括一个几何中心和物理重心3.编写一个程序,实现字符串的相关操作。
要求:在已有简单串类myString的基础上派生字符串类String1,类中包含返回字符串长度功能,并能使用运算符实现字符串连接与比较(不用库函数);设计一个具有编辑功能的串类String2,它从String1类派生而来。
成员函数能够在在字符串指定位置处实现如下操作:插入字符串、替换和删除某个字符,并能查找子串。
设计UML图见下4.综合性的实验,设计数组类族。
要求编写的程序涉及到C++的许多知识点,如类的定义,动态分配内存,构造函数,派生,虚基类等。
实验内容给出的是一个完整的程序,4个题目实际是类等级。
同学也可以在此基础上发挥增加新的内容。
1)定义一个基类MyArray,基类中可以存放一组数组。
编写构造函数,析构函数及其它函数,实现动态分配内存,释放内存和数据输入输出等功能。
并进行调试。
2)定义一个类averarray继承自myarray,在类中求数组的平均值,并输出。
实验报告课程名称面向对象程序设计系别机械与电子工程系班级N电信-091F学生姓名邓建平07学号24092200003任课教师齐琦南湖学院教务办实验五继承和派生(上)一、实验目的理解类的继承概念,能够定义和使用类的继承关系。
掌握派生类的声明与定义方法。
掌握公有、私有和保护派生的访问特性。
二、实验内容题目一设计一个大学的类系统,学校中有学生、教师、职员,每种人员都有自己的特性,他们之间又有相同的地方。
利用继承机制定义这个系统中的各个类及类上必需的操作。
注意:先对每类人的属性进行分析,看是否有抽象的可能。
代码:#include<iostream>using namespace std;class person{char *name;int age;public:person(){cout<<"the constructor of class person!\n";}~person(){cout<<"the dstructor of class person!\n";}};class student:public person{char *department;int level;public:student(){cout<<"the constructor of class student!\n";}~student(){cout<<"the constructor of class student!\n";}};class teacher:public person{char *major;int salary;public:teacher(){cout<<"the constructor of class teacher!\n";}~teacher(){cout<<"the constructor of class teacher!\n";}};class personnel:public person{char *position;public:personnel(){cout<<"the constructor of class personnel!\n";}~personnel(){cout<<"the constructor of class personnel!\n";}};void main(){student d1;teacher d2;personnel d3;}题目二:考虑大学的学生情况,试利用单一继承来实现学生和毕业生两个类,设计相关的数据成员及函数,编程测试继承的情况。
C 继承与派生实验报告1. 引言继承与派生是面向对象编程中的基本概念之一,C语言作为一门面向过程的编程语言,也支持继承与派生的概念。
本实验旨在通过编写代码演示C语言中的继承与派生的使用方法,加深对这一概念的理解。
2. 继承与派生的概念继承是一种面向对象编程中的重要概念,通过继承,派生类可以继承基类的属性和方法。
在C语言中,继承是通过结构体嵌套的方式实现的。
派生是继承的一种特殊形式,通过派生,派生类可以在基类的基础上增加新的属性和方法。
3. 实验步骤步骤一:定义基类首先,我们需要定义一个基类,基类包含一些公共的属性和方法。
在C语言中,我们可以使用结构体来定义类。
typedef struct {int x;int y;} Point;上述代码定义了一个名为Point的结构体,它包含了两个整型属性x和y。
这个结构体可以看作是基类。
步骤二:定义派生类接下来,我们可以定义派生类,派生类通过嵌套包含基类的结构体来实现继承。
typedef struct {Point base; // 基类结构体int z; // 派生类自己的属性} Point3D;上述代码定义了一个名为Point3D的结构体,它嵌套包含了基类Point的结构体,并新增了一个整型属性z。
这个结构体可以看作是派生类。
步骤三:使用派生类在定义好派生类后,我们可以使用派生类来创建对象,并调用基类的属性和方法。
int main() {// 创建对象Point3D point3d;point3d.base.x = 1;point3d.base.y = 2;point3d.z = 3;// 调用基类属性printf("x: %d\n", point3d.base.x);printf("y: %d\n", point3d.base.y);// 调用派生类自己的属性printf("z: %d\n", point3d.z);return0;}上述代码示例了如何使用派生类创建对象,并访问基类的属性和派生类自己的属性。
C 继承与派生实验报告C 继承与派生实验报告引言:在计算机编程领域,继承与派生是一种重要的概念。
通过继承,我们可以构建更加复杂和灵活的程序结构,提高代码的可重用性和可维护性。
本实验旨在通过实际操作和分析,深入理解C语言中继承与派生的原理和应用。
实验目的:1. 理解继承与派生的概念和原理;2. 掌握C语言中继承与派生的语法和用法;3. 实践继承与派生的应用,加深对其理解。
实验步骤:1. 创建基类和派生类:首先,我们创建一个基类Animal,其中包含一个成员函数eat()和一个成员变量name。
然后,我们创建一个派生类Dog,继承自基类Animal,并添加一个成员函数bark()和一个成员变量breed。
2. 实现继承与派生的功能:在基类Animal中,实现成员函数eat(),用于输出动物的进食行为。
在派生类Dog中,实现成员函数bark(),用于输出狗的吠叫行为。
同时,通过继承,派生类Dog可以直接访问基类Animal中的成员变量name。
3. 测试继承与派生的效果:在主函数中,创建一个Dog对象,并调用其成员函数eat()和bark(),以验证继承与派生的功能是否正常工作。
同时,可以通过修改派生类Dog的成员变量breed,观察其对程序运行结果的影响。
实验结果与分析:通过实验,我们可以发现继承与派生的强大功能。
基类Animal提供了一种通用的行为eat(),而派生类Dog则通过添加成员函数bark(),实现了更加具体和特定的行为。
这种继承与派生的关系,使得我们可以在保留原有功能的基础上,进行灵活的扩展和定制。
此外,通过继承,派生类Dog可以直接访问基类Animal中的成员变量name。
这种继承的特性,使得派生类可以共享基类的数据,避免了重复定义和冗余代码的问题。
同时,通过修改派生类Dog的成员变量breed,我们可以看到其对程序运行结果的影响。
这种灵活性,使得我们可以根据具体需求,定制不同的派生类,实现更加个性化的功能。
第一节类的继承与派生一、基本概念继承是面向对象程序设计的一个特性,所谓继承就是在已有类的基础上创建新的类,新类可以从一个或多个已有类中继承成员函数或数据成员,而且新类还可以重新定义或加进新的数据和函数。
其中,已有类称为基类或父类,新类称为派生类或子类。
在现实世界中许多事物都具有继承性。
例如:“汽车”这个类中包括了许多类型,有运输汽车、专用汽车;运输汽车中又包括客车、货车…….;专用汽车中又包括巡逻车、消防车、救护车……..;所有这些类型的车都具有汽车的共同特性即都有发动机、车身、轮胎等共性,还都是自行驱动的。
而客车和货车又有所不同,客车用来载客,货车用来拉货,它们有自己不同于其它车的特性,这就是继承。
我们把汽车称为基类,把运输汽车、客车、货车称为派生类。
通过继承,派生类不仅拥有了基类的属性和行为,而且具有不同于它类的自己的特点。
二、派生类的定义与构成当你去水果店买水果的时候,你经常会发现很多同类水果又有了新的品种。
比如,“李子”既小又涩,嫁接在梨树上后长出来的李子却硕大、香甜、清脆,比没有嫁接的李子好吃,但它还是李子家族中的一员;所以,可以认为“嫁接李子”是从“李子”中派生出来的。
当然,可以把“李子”嫁接在梨树上,也可以嫁接在苹果树上,结出来的都是“李子”,但是各自味道不同。
所谓派生就是从已有类中产生一个新的子类。
基类就是已存在的可以派生新类的类,如下图中的A、D、E都是基类。
派生类就是由基类派生出来的新类,如下图中的B、C、F都是派生类。
1. 单继承派生类的定义格式class <派生类名> : <继承方式> <基类名>{派生类成员的定义;};其中,“派生类名”是新定义的一个类的名字,它是从“基类名”中派生的,并且按指定的“继承方式”派生。
例如:class peach 多继承派生类的定义格式class <派生类名> :<继承方式1> <基类名>,<继承方式2> <基类名>, …….{派生类成员的定义;};多继承与单继承在定义格式的区别仅在于它们的基类个数不同,单继承的基类只有一个,而多继承的基类有多个,相邻两个基类之间用逗号间隔,每个基类名前都应有一个该基类的继承方式的说明符。
例如:class peach //定义基类:peach{datatype color , shape ;};class apple //定义基类:peach{datatype color, shape , weight ;};class sweetpeach : public peach, public apple // 多继承{datatype color, shape, taste;};类sweetpeach 同时继承自类peach 和类apple,这就是多继承。
3.继承的作用有的读者可能会问为什么要有继承,继承有什么好处,继承的作用是什么为了解决这些疑问,我们一起来分析以下例子,从中领悟继承的奥妙。
【例10-1-1】分析以下代码。
声明一个person 类,它包含的成员有name(姓名)、age (年龄)、gender(性别),和output函数,具体定义如下:class person{public :char name[8] ;int age;char gender ;public :void output() { }};现在要声明一个student类,它包含的成员有name(姓名),age(年龄),gender(性别),department(系),stuno(学号),address(住址),和output函数,具体定义如下:class student{public :char name[8] ;int age;char gender;char department[20] ;int stuno;int address;public :void output() { }};从这两个类的声明中可以看出,它们中有些成员数据和成员函数是相同的。
这样就存在代码的重复,为了提高代码的可重用性,就引入了继承。
即,如果student类以共有继承的方式继承person类,那么student类就可以直接使用person类中的共有成员如name, gander,age和output() 函数,这样在student类中就不需要再定义与person类中相同的变量了,只定义person类中没有的在student类中需要的变量。
具体实现如下:class student : public person // student共有继承person类{public :char department[20] ;int stuno ;int address ;public :void output() { }};提示student 类称为派生类,person类成为基类;关键字public 的作用是说明派生类公有继承了基类中的所有成员,即派生类可以直接访问基类的成员;继承可以使代码得以重用,提高工作效率。
三、派生类访问基类成员通过前面的学习大家都知道基类的成员有public(公有)、protected(保护)、private(私有)3种访问属性,基类的自身成员可以对基类中任何一个其他成员进行访问,但是通过基类的对象就只能访问该类的公有成员。
派生类可以继承基类中除了构造函数和析构函数之外的全部成员,但是这些成员的访问属性在派生过程中是可以调整的。
从基类继承来的成员在派生类中的访问属性是由继承方式控制的。
不同的继承方式导致原来具有不同的访问属性的基类成员在派生类的访问属性也有所不同。
在派生类中,从基类继承来的成员可以访问属性有4种:不可直接访问的成员、public (公有成员)、protected(保护成员)、private(私有成员)。
1.三种继承方式的声明public 公有继承公有继承:在定义一个派生类时将基类的继承方式指定为public 的继承方式。
例如:class student : public person { }private 私有继承私有继承:在定义一个派生类时将基类的继承方式指定为private的继承方式。
例如:class student : private person { }protected 保护继承保护继承:在定义一个派生类时将基类的继承方式指定为protected的继承方式。
例如:class student : protected person { }2.三种继承方式的区别如表1指明了三种继承方式的区别,即派生类对基类成员的访问能力。
表 1 三种继承方式的区别在基类中的访问属性继承方式在派生类中的访问属性private public不可直接访问private private不可直接访问private protected不可直接访问public public publicpublic private privatepublic protected protectedprotected public protectedprotected private privateprotected protected protected提示在任何继承方式中基类中的私有成员都不允许派生类继承,即在派生类中是不可直接访问基类中的私有成员。
当类的继承方式为公有继承时:基类中的所有公有成员在派生类中仍为公有成员;基类中的所有保护成员在派生类中仍为保护成员。
当类的继承方式为私有继承时:基类中的所有公有成员在派生类中都为私有成员;基类中的所有保护成员在派生类中都为私有成员。
当类的继承方式为保护继承时:基类中的所有公有成员在派生类中都为保护成员;基类中的所有保护成员在派生类中仍为保护成员。
派生类对基类成员的访问形式主要有以下两种:(1) 内部访问:由派生类中的新增成员对从基类继承来的成员的访问。
(2) 对象访问:在派生类外部,通过派生类的对象对从基类继承的成员的访问。
现在分别讨论在公有继承、私有继承、保护继承这3种继承方式下,派生类对基类成员的访问规则。
一、公有继承【例1】分析以下程序。
源代码:#include <>#include <>class Base{private:int pvx; //pvx为基类私有变量protected :int pty; //pty为基类保护变量public :float puf; //puf为基类公有变量void Setxy(int q, int u, float w) //Setxy()为基类公有函数{pvx = q ; pty = u; puf = w;}void Output() //Output()为基类公有函数{cout << "class Base output "<< endl;cout << "pvx= " << pvx << endl;cout << "pty= " << pty << endl;cout << "puf= " << puf << endl;}};class Derive : public Base //公有单继承{private :float pvz;public :void Setvalue(int x, int y, float f, float z){Setxy(x, y, f);pvx = x; //非法访问,基类中的pvx为private属性,不能被继承pty = y; //合法访问puf = f; //合法访问pvz = z;}void Print(){cout << "pvx= " << pvx << endl;// 非法访问,在基类中pvx为私有成员cout << "class Derive output " << endl;cout << "pty= "<<pty << endl; // 合法访问,在基类中pvy为保护成员cout << "puf= "<<puf << endl; // 合法访问,在基类中puf为公有成员cout << "pvz= "<<pvz << endl; // 合法访问,pvz为派生类自己的成员}};void main(){Derive obj;(3,5, , ;();();cout << "puf= " << << endl; //合法访问,puf为基类公有成员cout<<<<endl; // 非法访问,类的外部不能访问为基类保护成员ptysystem("pause");}运行输出:class Base outputpvx= 3pty= 5puf=class Derive outputpty= 5puf=pvz=puf=【简要分析】①“class Derive : public Base { }”表明这是一个公有继承的例子,基类Base中有3个变量和两个函数:私有变量pvx、保护变量pty、公有变量puf和公有函数Setxy()、Output()。