实验五类的继承与派生
实验五 继承与派生2(报告)

验
内
容
创建一个表示雇员信息的employee类,其中包含数据成员name、empNo和salary,分别表示雇员的姓名、编号和月薪。再从employee类派生出3个类worker、technician和salesman,分别代表普通工人、科研人员、销售人员。三个类中分别包含数据成员productNum、workHours和monthlysales,分别代表工人每月生产产品的数量、科研人员每月工作的时数和销售人员每月的销售额。
2、派生类的定义(worker普通工人类、technician科研人员类和salesman销售人员类)
worker普通工人类的定义,公有继承employee,增加变量productNum(产品数量)与profit(每件产品的利润)及用来计算雇员月薪pay()函数(计算员工月工资并输出)。
technician科研人员类公有继承employee,增加变量workHours(工作时间)及hoursalary(每小时的工资)及pay()函数(功能同上)。
salesman销售人员类也是公有继承employee,增加monthlysales(月销售额)、ti_cheng(销售额提成)及pay()函数(功能同上)。
如上图主函数。定义三个不同工种的员工,并输出信息。
实
验
结
果
运行结果:
出
现
的
问
题
及
解
决
方
案
程序编译一次成功了,这次没有意外。
课程名称
C++程序设计A2
班级
1420561
实验日期
2015.01.01
姓名
刘翔翔
学号
21
实验成绩
C 继承与派生实验报告

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++ 6.0实验五类和对象、继承和派生

上海电力学院实验报告课程名称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”按钮,弹出“保存为”文件对话框。
C++面向对象程序设计实验五 派生与继承
学长只能帮你到这了
要想学习好,努力少不了
int b; };
void main() {
CDerive d; d.print(); CBase b; b.print(); }
问题一:以上程序有两大错误,试指出来,并改正之? 答:CBase 类中 print 为保护成员对象不可直接访问。派生类中没有构造函数,加一个构造 函数并对参数初始化。CDerive(int n,int a):CBase(a) {b=n;}
要想学习好,努力少不了
实验五 派生与继承—单重派生
5.1 实验目的
1.理解继承的含义以及声明; 2.理解共有派生、私有派生和保护派生的含义以及使用; 3.理解单派生类中构造函数和析构函数的调用顺序。
5.2 实验内容
5.2.1 程序阅读
1.理解下面的程序,并在 VC++6.0 下运行查看结果,回答程序后面的问题。
要想学习好,努力少不了
S=pi*R*R; cout<<"位于点"<<"("<<x1<<","<<y1<<")"<<"处圆的面积 S="<<S<<endl; } ~CCircle(){} private:double R,S; }; void main() { double x1,y1,x2,y2,R; cout<<"请输入 a 点 x 和 y 的坐标:"; cin>>x1>>y1; CPoint a(x1,y1);a.print(); CLine b(x1,y1,x2,y2); cout<<"请输入圆心坐标:"; cin>>x1>>y1; CCircle D(x1,y1); } 2. #include "iostream.h" #include<cmath> #define pi 3.14159 class CPoint { public: CPoint(double x1=0,double y1=0) {
实验5类和对象、继承和派生
程序Ex_Class:定义一个人员类CPerson,包括数据成员:姓名、编号、性别、和用于输入、输出的成员函数。在此基础上派生出学生类CStudent(增加成绩)和教师类CTeacher(增加教龄),并实现对学生和教师信息的输入、输出。编写一个完整的测试程序,并将Ex_Class所有的类定义保存在Ex_Class.h,将类的成员函数实现代码保存在Ex_Class.cpp中。
stu.student.setSex(0);
stu.InputScore(80,90,85);
stu.Print();
CTeacher tea(" Ding","911085");
tea.Print();
tea.setID("9110234");
tea.Print();
}
(2)单击标准工具栏的“Save”按钮,弹出“保存为”文件对话框。将文件保存为Ex_Class.cpp。
}
//主函数
void main()
{ CStudent stu(" LiMing"," 21010211" );
cout<<stu.getName()<<endl;
cout<<stu.student.getName()<<endl;
stu.Print();
stu.student.setName(" LingLing");
3输入程序Ex_Class.cpp
(1)单击标准工具栏上的“New Text File”按钮,在新打开的文档窗口中输入下列程序代码:
#include<iostream.h>
实验五 继承与派生实验报告
实验五继承与派生一、实验目的( 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表示行驶和停止。
实验报告-类的派生与继承
return 0;
}
4.模拟银行ATM终端系统,ATM机上可以使用储蓄卡和信用卡。储蓄卡有存钱、取钱、查询余额、修改密码等功能。信用卡有存钱、查询额度、查询本期账单金额、查询未出账单总金额、修改密码等功能。请用面向对象方法编程实现上述功能。
#include<iostream>
{
return weight;
}
void setWheels(int ws)
{
wheels = ws;
}
void setWeight(float wt)
{
weight = wt;
}
void display()
{
cout << "车轮数:" << wheels << "汽车承重:" << weight << endl;
cout << "请输入部门:";
cin >> bumen;
}
void display()
{
user::display();
cout << " 职称:" << zhicheng << " 部门:" << bumen << endl;
}
private:
char zhicheng[20];
char bumen[20];
cin >> hour;
sumsalary = salary + 5 * hour;
}
void display()
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一节类的继承与派生一、基本概念继承是面向对象程序设计的一个特性,所谓继承就是在已有类的基础上创建新的类,新类可以从一个或多个已有类中继承成员函数或数据成员,而且新类还可以重新定义或加进新的数据和函数。
其中,已有类称为基类或父类,新类称为派生类或子类。
在现实世界中许多事物都具有继承性。
例如:“汽车”这个类中包括了许多类型,有运输汽车、专用汽车;运输汽车中又包括客车、货车…….;专用汽车中又包括巡逻车、消防车、救护车……..;所有这些类型的车都具有汽车的共同特性即都有发动机、车身、轮胎等共性,还都是自行驱动的。
而客车和货车又有所不同,客车用来载客,货车用来拉货,它们有自己不同于其它车的特性,这就是继承。
我们把汽车称为基类,把运输汽车、客车、货车称为派生类。
通过继承,派生类不仅拥有了基类的属性和行为,而且具有不同于它类的自己的特点。
二、派生类的定义与构成当你去水果店买水果的时候,你经常会发现很多同类水果又有了新的品种。
比如,“李子”既小又涩,嫁接在梨树上后长出来的李子却硕大、香甜、清脆,比没有嫁接的李子好吃,但它还是李子家族中的一员;所以,可以认为“嫁接李子”是从“李子”中派生出来的。
当然,可以把“李子”嫁接在梨树上,也可以嫁接在苹果树上,结出来的都是“李子”,但是各自味道不同。
所谓派生就是从已有类中产生一个新的子类。
基类就是已存在的可以派生新类的类,如下图中的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()。