实验四 继承与派生讲解学习

合集下载

c 继承与派生实验报告

c 继承与派生实验报告

c 继承与派生实验报告
C 继承与派生实验报告
实验目的:通过实验,掌握C语言中继承与派生的概念和使用方法,加深对面向对象编程的理解。

实验内容:在C语言中,继承与派生是面向对象编程中非常重要的概念。

在本次实验中,我们将通过一个简单的例子来演示C语言中的继承与派生的用法。

首先,我们定义一个基类(父类)Person,包括姓名和年龄两个成员变量,以及一个显示信息的成员函数。

然后,我们定义一个派生类(子类)Student,继承自Person类,新增一个成员变量学号,并重写显示信息的成员函数。

在实验中,我们首先创建一个Person对象,设置姓名和年龄,然后调用显示信息函数,观察结果。

接着,我们创建一个Student对象,设置姓名、年龄和学号,再次调用显示信息函数,观察结果。

实验结果:通过实验,我们成功实现了C语言中的继承与派生。

我们发现,通过继承,子类Student可以直接使用父类Person中的成员变量和成员函数,同时可以新增自己的成员变量和函数。

这样的设计使得代码更加简洁和灵活,提高了代码的复用性和可维护性。

结论:C语言中的继承与派生是面向对象编程中非常重要的概念,通过本次实验,我们深入理解了这一概念的用法和意义。

掌握了继承与派生的方法后,我们可以更加灵活地设计和编写程序,提高代码的质量和效率。

总结:通过本次实验,我们对C语言中的继承与派生有了更深入的理解,加深了对面向对象编程的认识。

在今后的学习和工作中,我们将更加灵活地运用继承与派生的方法,提高代码的质量和效率。

实验四 继承与派生1(报告)

实验四 继承与派生1(报告)




Visual Studio 2010




编写程序计算出球、圆柱、圆锥,都含有求表面积和体积。
要求:
(1)定义一个基类圆类至少含有一个数据成员半径;
(2)定义基类成员的派生类:球、圆柱、圆锥,都含有球表面积和体积的成员函数和输出函数。
(3)在主函数中求球、圆柱、圆锥的表面积和体积。









1、基类圆的定义
ห้องสมุดไป่ตู้如上图,包含半径、周长、面积,能够输出圆的基本信息。
2、派生类的定义(球、圆柱、圆锥)
派生类球(Ball)的定义,公有继承Circle,增加变量表面积S与体积V及输出函数。
派生类圆柱(Column)公有继承Circle,增加自己的属性变量高high及表面积S、体积V,输出函数。
派生类圆锥(Cone)也是公有继承Circle,增加高high、表面积S、体积V和输出函数。
如上图主函数。




第一次运行结果:
第二次运行结果:










程序编译一次成功了,但运行结果不对。原因是在计算圆锥体积和球的体积时要用到两个分数1/3、4/3参与运算,但在计算机中这两个分数是由两个整形变量计算而来的,其结果也是一个整形变量(0和1),所以运行结果错误,将其改成1.0/3与4.0/3即可,这样就是两个float型变量计算,结果也是我们要的结果了。
课程名称
C++程序设计A2
班级
1420561

实验继承与派生

实验继承与派生

实验项目:继承与派生实验目的: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设置成非虚基类,在编译一次,此时系统报错,无法编译成功。

实验四:派生类和继承(一)

实验四:派生类和继承(一)

福建农林大学实验报告实验4 派生类和继承(一)一、实验目的和要求(1)掌握派生类的声明与定义方法,进一步理解类的继承的概念,能够定义和使用类的继承关系。

(2)熟悉公有派生和私有派生的访问特性。

二、实验内容和原理1、(1)定义一个基类Animal,该类具有私有整型成员变量age,weight,构造派生类Dog公有继承Animal。

Dog类新增私有成员变量color,新增成员函数SetAge(int n)中直接给age赋值,新增成员函数SetWeight(int m)中直接给weight赋值,查看编译结果,并分析结果。

(2)将类Anima l中的age和weight为公有成员,重做第一步,并分析结果。

(3)将类Animal中的age和weight 为保护成员,重做第一步,并分析结果。

(4)将派生类Dog的继承方式改为私有继承方式和保护继承方式重做以上各小题,并分析结果。

2、程序分析题(写出程序的输出结果,并分析结果)。

三、实验环境1. 硬件:PC机;2. 软件:Windows操作系统、Visual C++ 6.0四、算法描述及实验步骤1、(1):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<"Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";cin>>y;cout<<endl;cout<<"The dog's age is "<<a.SetAge(x)<<endl;cout<<"The dog's age weight is"<<a.SetWeight(y)<<endl; return 0;}(2):#include <iostream.h>class animal{public:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";return 0;}(3):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";cin>>y;cout<<endl;cout<<" The dog's age is "<<a.SetAge(x)<<endl;cout<<" The dog's age weight is "<<a.SetWeight(y)<<endl; return 0;}(4):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";return 0;}(5):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";cin>>y;cout<<endl;cout<<" T The dog's age is "<<a.SetAge(x)<<endl;cout<<" The dog's age weight is "<<a.SetWeight(y)<<endl; return 0;}(6):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";return 0;}(7):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";cin>>y;cout<<endl;cout<<" The dog's age is "<<a.SetAge(x)<<endl;cout<<" The dog's age weight is "<<a.SetWeight(y)<<endl; return 0;}(8):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";return 0;}(9):#include <iostream.h>class animal{private:int age,weight;};class dog:public animal{private:char color[10];public:int SetAge(int n){age=n;return n;}int SetWeight (int m){weight=m;return m; }};int main(){ int x,y;dog a;cout<<" Please input dog's age :";cin>>x;cout<<endl;cout<<" Please input dog's weight:";cin>>y;cout<<endl;cout<<" The dog's age is "<<a.SetAge(x)<<endl;cout<<" The dog's age weight is "<<a.SetWeight(y)<<endl; return 0;}2#include<iostream.h>class A{public: A(int i,int j){a=i;b=j;}void move(int x,int y){a+=x;b+=y;}void display(){cout<<"("<<a<<","<<b<<")"<<endl;} private:int a,b;};class B:public A{public: B(int i,int j,int k,int l):A(i,j),x(k),y(l){}void display(){cout<<x<<","<<y<<endl;}void fun1(){move(13,15);}void fun2(){A::display();}void fun3(){display();}private:int x,y;int main(){A aa(2,4);aa.display();B bb(5,6,7,8);bb.fun1();bb.fun2();bb.fun3();bb.A::display();bb.B::display();return 0;}五、调试过程1、调试程序,截图如下:原因分析:在public继承中void display 中的display打错成diaplay。

实验四 继承与派生(学生)

实验四  继承与派生(学生)

实验四:继承与派生(2)一、实验目的和要求(1)理解单继承与多继承,掌握多继承派生类的声明方式。

(2)掌握多继承派生类构造函数的定义的一般形式。

(3)掌握多继承构造函数与析构函数的执行顺序。

(4)掌握含有对象成员的派生类构构造函数的特点。

(5)理解类的继承可能发生的“二义性”问题(同名成员的访问)二、知识点回顾多继承构造函数定义的一般形式如下:派生类名(参数总表):基类名1(参数表1),基类名2(参数表2),…,基类名n(参数表n) {// 派生类新增成员的初始化语句}class B: public A class D:public A, public B, public C{ {B(int i,int j):A( i){ ….. D(int i,int j,int k, int l):A( i),B(j ),C( k),ob(l ) } { …….}}; };…….D obj(1,2,3,4);多重继承构造函数的执行顺序与单继承下的构造函数执行顺序相同:(1)先执行基类的构造函数。

(2)再执行对象成员的构造函数。

(3)最后执行派生类的构造函数体。

说明:处于同一层的各个基类的构造函数的执行顺序, 取决于声明派生类时所指定的各个基类的顺序, 与派生类构造函数中所定义的成员初始化列表中的顺序并没有关系.说明:派生类构造函数后如未列出基类构造函数的调用,默认调用的是无参或带默认参数的构造函数。

三、实验内容1. P191题4.15输入下列程序,分析程序运行结果........。

理解多重继承(画出类的层次结构图),注意派生类构造函数的定义格式,注意构造函数的执行顺序,注意同名成员的访问。

#include<iostream>#include<string>using namespace std;class B1{int b1;public:B1(int i){b1=i;cout<<"Construcor B1."<<i<<endl;}void print(){ cout<<b1<<endl;}};class B2{int b2;public:B2(int i){b2=i;cout<<"Construcor B2."<<i<<endl;}void print(){ cout<<b2<<endl;}};class B3{int b3;public:B3(int i){b3=i;cout<<"Construcor B1."<<i<<endl;}int getb3(){ return b3;}};class A:public B2,public B1{int a;B3 bb;public:A(int i,int j,int k,int l):B1(i),B2(j),bb(k) //此处注意派生类构造函数的定义格式{a=l;cout<<"Constructor A."<<l<<endl;}void print() //{ B1::print(); //同名成员的访问,注意消除二义性B2::print(); //同名成员的访问cout<<a<<","<<bb.getb3()<<endl;}};int main(){ A aa(1,2,3,4);aa.print(); //分析调用的是哪个print(). 同名覆盖(将基类的同名成员隐藏)return 0;}在以上程序的基础上,为每个类增加一个析构函数,析构函数体内容“Destructor X”,其中X写成具体的类名。

实验四 继承与派生

实验四  继承与派生

实验四继承与派生一. 实验目的:1.了解继承与派生的概念,掌握派生类声明的方式和派生类的构成。

2. 掌握派生类成员的访问属性。

3. 掌握派生类构造函数的定义方法。

4. 掌握多重继承的方法。

5. 掌握虚基类的使用。

6. 掌握基类与派生类的转换关系。

二. 实验类型:验证型实验和设计型实验三. 验证型实验内容:1.编写运行下面程序,体会继承与派生的概念,学习派生类声明的方式并了解派生类的构成。

#include <iostream>#include <string>using namespace std;class Person //声明基类{public:void set_person(char[],int,char);void display_person( );private :char name[20];int age;char sex;};void Person::set_person(char na[],int a,char s){strcpy(name,na);age=a;sex=s;}void Person::display_person( ){ cout<<"name:"<<name<<endl;cout<<"age:"<<age<<endl;cout<<"sex:"<<sex<<endl;}class Student: public Person //声明派生类{ public:void set_student(char[],int,char,int,char[],int); //派生类新增加成员函数void display_student( ); //派生类新增加成员函数private:int num; //派生类新增加数据成员char speciality[20]; //派生类新增加数据成员int grade; //派生类新增加数据成员};void Student::set_student(char na[],int a,char s,int n,char sp[],int g)//设置派生类中全部数据成员{set_person(na,a,s); //调用派生类继承的基类成员函数num=n;strcpy(speciality,sp);grade=g;}void Student::display_student( ) //显示派生类中全部数据成员{ display_person( ); //调用派生类继承的基类成员函数cout<<"num:"<<num<<endl;cout<<"speciality:"<<speciality<<endl;cout<<"grade:"<<grade<<endl;}int main( ){Student s; //定义派生类对象s.set_student("wang",21,'m',20060701,"JAVA",2);s.display_student();return 0;}提示:在开发环境中,通过在派生类对象后面输入成员访问运算符可以看到派生类中的成员列表,了解派生类的构成。

C _4_继承和派生

C  _4_继承和派生

第四章继承和派生§4—1 继承§4—2 单继承§4—3多继承§4—1 继承一、继承的含义①面向对象方法提供了从问题域到解域的自然映射客观世界中的对象既有共性,也有个性,通过不同程度的抽象,形成了分类和层次结构不同层次的类之间体现了概括(generalize)和特化(specify)关系把高层次的类称为父类、超类和基类,把由该类特化产生的低层次类称为子类或派生类派生类不仅具有基类的属性和行为,还具有自己特有的属性和行为②在不同类之间,除了概括和特化的关系外,还有聚合和分解关系模块化的主要目的是实现软件的可复用性从模块的角度看,继承是一种关键性的复用技术③继承机制提供了一种充分利用现有资源的方法它既体现了经济思想,又体现了谦虚精神:我比别人看得远,是因我站在巨人的肩上——牛顿继承使得在创建新类时,只需说明新类与基类的区别,从而大量原有代码都可复用④派生类是基类的具体化,是基类定义的延续在多继承时,派生类也是基类的组合二、继承的概念1.基类即父类,超类,是已存在的用来派生新类的类,是被继承的类2.派生类即子类,是由己存在的类派生出的新类,是继承其他类特性的类3.单继承即单重继承,每个派生类只有一个直接父类是从一个基类派生的继承,形成类的层次,像一棵树4.多继承即多重继承,派生类可以有多个直接父类是从多个基类派生的继承,形成一个有向无环图(DAG图)5.类的层次结构直接基类、间接基类、直接派生类、间接派生类多层继承:一个基类可以是另一个基类的派生类区别:多层继承和多重继承三、派生类的定义①单继承class 派生类名: 继承方式基类名{派生类新定义成员;};②多继承class 派生类名: 继承方式1 基类名1,继承方式2 基类名2,……{派生类新定义成员;};四、继承方式共有三种:公有继承:public保护继承:protected私有继承:private 可缺省继承方式基类特性派生类特性公有继承public publicprotectedprivatepublicprotected不可访问或不可见保护继承public protectedprotected protectedprivate protected 不可访问私有继承(缺省)private publicprotectedprivateprivateprivate不可访问派生类不能继承基类的构造函数、析构函数和友元1.基类的私有成员只能被基类中的成员函数和友元函数访问,不能被其他函数访问2.基类的保护成员只能被基类及其派生类中的成员函数和友元函数访问3.公有继承派生类的对象可以访问基类中的公有成员派生类的成员函数可以访问基类中的公有成员和保护成员4.保护继承和私有继承派生类的对象不能访问基类中的任何成员派生类的成员函数可以访问基类中的公有和保护成员5.私有继承基类的公有和保护成员只能由直接派生类访问,无法再往下继承§4—2 单继承每个派生类只有一个直接基类,但每个基类可以有多个派生类一、成员访问权限的控制二、成员访问权限的调整①保护继承和私有继承将改变基类的公有和保护成员在派生类中的访问权限属性,若欲恢复其访问权限,则应作调整②方法:在派生类相应访问权限段中加以说明:基类名:: 成员名;③访问声明只能对变量或函数名,不能说明类型和参数④基类成员被调整后,在派生类中的访问权限既不能扩大也不能减小,即不能改变所属权限段⑤私有成员的访问权限不可调整,不能对私有段成员作访问声明⑥重载函数只需一个声明即可,具有不同访问权限的重载函数名不能作访问声明三、派生类的成员(1)由两部分组成:①派生类从基类继承来的成员,其封装体叫基类子对象(匿名对象)②派生类自定义成员(2)派生类对象的内存长度是基类数据成员和派生类自定义数据成员的内存空间之和(3)基类的私有成员在派生类中存在,但不可访问,不可见(4)静态成员受访问权限符的限制,但不受继承方式的制约派生类可用“基类名:: 静态成员名”访问基类的static成员(5)派生类共有四种成员:①公有成员②保护成员③私有成员④不可直接访问的成员,它由基类私有成员派生而来的(6)派生类直接访问基类私有成员的方法:①将基类私有段成员放于基类保护段②将派生类或派生类的成员函数声明为基类的友元四、改造基类成员(1)通过继承方式来控制基类成员在派生类中的访问权限(2)对基类成员进行同名覆盖①在派生类中声明一个与基类成员同名的新成员以屏蔽(隐藏)基类同名成员②在派生类中或通过派生类对象只能访问到派生类中新定义的同名成员③若在派生类中欲调用被编译器隐蔽起来的基类同名成员,则应作访问声明,明确指定基类类范围:对象名.基类名:: 成员名对象名.基类名:: 成员函数名(参数表)④同名覆盖时要求派生类与基类同名的新成员函数原型相同,数据成员的名字和类型相同当同名的基类成员函数和派生类成员函数的参数个数、类型和顺序不完全相同时,则属于函数重载⑤当欲对从基类继承过来的某些函数功能进行扩充和改造时,都可用同名覆盖原则来实现五、派生类的构造函数(1)派生类对象的数据结构,由基类数据成员和派生类自定义数据成员共同构成(2)构造函数不能被继承,基类子对象只能通过基类构函来初始化,常以成员初始化列表方式进行(3)定义:派生类名(总参数表):基类名(参数表),子对象名(参数表2),……{派生类自定义数据成员的初始化;}(4)派生类构造函数的调用执行顺序:①基类构造函数:先兄长②子对象类的构函:后客人③派生类构函:最后自己(5)当基类有无参数或缺省构函或未显式定义任何构函时,派生类构函中可省去对基类构函的调用(6)当基类构函有参数时,则派生类必须定义构函,以提供参数传递的途径(7)当派生类的基类也是一个派生类时,则每个派生类只需负责其直接基类构函的调用六、派生类的析构函数(1)析构函数不能被继承,基类子对象只能通过基类析构函数类释放(2)析构函数调用执行顺序与构函相反:①派生类析构函数:先自己②子对象类析构函数:再客人③基类析构函数:最后兄长七、赋值相容原理(1)即当派生类从基类公有继承时,派生类对象可自动隐式地转换一个基类对象(2)当公有继承时,在需要基类对象的任何地方,都可以使用公有派生类的对象来替代即公有派生类对象可以作为基类对象使用,但只能使用从基类继承来的成员(基类子对象)(3)公有派生类的对象、对象指针、对象引用都适用于基类对象、对象指针、对象引用所能使用的场合(4)赋值相容性不可逆若欲将基类对象指针转换成公有派生类对象指针,则必须显式进行类型转换不允许用基类对象给派生类对象赋值(5)也称为子类型对父类型的类型适应①子类型:对类型S,当且仅当它至少提供了类型T的行为,则称S是T的子类型②公有继承时,基类为父类型,派生类为子类型,派生类适应于基类③类型适应:若一个函数可用于父类型的对象,则它也可用于其各个子类型的对象(6)是多态性的基础,提高了编程效率八、多层继承(1)所有派生类都只需对其直接基类负责:派生类构函只需向其直接基类传递参数(2)可实现抽象机制和软件重用机制§4—3多继承一、多继承即多重继承①是单继承的扩展和组合,单继承可看作是多继承的特例②派生类有两个或两个以上的直接基类③派生类与每个基类之间仍可看作单继承④赋值相容性原理对多继承同样成立⑤同名覆盖规则对多继承仍成立⑥一个类不能多次被说明为同一个派生类的直接基类,即一个类不可以从同一个类中直接继承一次以上(可改用子对象方式)⑦可采用DAG图示法来表示各个基类与派生类的关系:箭头指向基类⑧一个类可以多次成为同一个派生类的间接基类二、多继承的构造函数与析构函数(1)定义:派生类名(总参数表):基类名1(参数表1),基类名2(参数表2),…,子对象名(参数表n),……{派生类构造函数体;}(2)派生类构函调用执行顺序:(与单继承相同)①先执行基类构函:先兄长②再执行子对象类构函:再客人③最后执行派生类本身的构函:最后自己(3)处于同一层次的各基类构函的执行顺序取决于定义派生类时所指定的各基类顺序,与派生类构函定义的成员初始化列表各项顺序无关(4)析构函数的调用执行顺序与构函相反三、多继承中的二义性问题(1)即派生类对基类成员访问的不唯一性(继承的模糊性)(2)调用不同基类的相同成员时可能出现二义性措施:使用作用域运算符,用类名对成员加以限定3)访问共同基类的成员时可能出现二义性措施:①用类名限定法来消除二义性,只能用派生类的直接类名来限定②在派生类中重定义一个与基类中同名的成员,以覆盖之③将公共基类说明为虚基类,使之在派生类中只有一个拷贝4)二义性检查是在访问控制和类型检查之前进行的,故只要不同基类有同名成员时,均会出现二义性,即使只有一个可被派生类访问或只有一个名字的类型符合要求(5)存在二义性,则编译时出错§4—4 虚基类1.即虚拟基类2.若类A是派生类C多条继承路径上的一个公共基类,则A在C的对象中将产生多个基类子对象若欲使其只有一个拷贝,则需将A设置为虚拟基类3.引入虚基类的目的:解决二义性问题,使派生类中只有公共基类的一个数据副本4.定义:class 派生类名:virtual 继承方式基类名5.虚基类子对象只被初始化一次,虚基类构函也只被执行一次6.若虚基类构函带有参数,则其直接或间接派生类的构函成员初始化列表中均应列出对虚基类构函的调用,但只有最后派生出来的用于声明对象的类对虚基类构函的调用才会被执行7.在同一层次中,虚基类构函先于非虚基类构函执行8.可节省内存空间,程序也更简洁9.一个类在作为某些类的虚基类的同时,还可以作为另一些派生类的非虚基类10.若虚基类由非虚基类派生而来,则先调用基类构函,再调用派生虚基类构函11.virtual常用于声明虚基类的直接派生类,可放于继承方式前,也可放于继承方式后面12.多继承时,virtual后紧跟的基类为虚基类,若有多个虚基类,则应用多个virtual来说明13.若同一层次中有多个虚基类,则其构函执行顺序取决于派生类定义时指定的顺序。

继承与派生实验报告

继承与派生实验报告

计算机科学与技术学院程序设计报告程序名称:继承与派生(一)专业:计算机科学与技术班级:计算机1103班学号:姓名:指导老师:设计日期:2012年4月13日实验四继承与派生(一)[实验目的]1、掌握类继承与派生关系以及实现方法,理解类的层次结构;2、掌握派生类构造函数初始化基类成员和对象成员的方法;3、掌握赋值兼容原则,掌握派生类的复制构造函数的定义。

[实验内容与步骤]题目:由例题1中的point类和circle类继续派生出cylinder,求其表面积Area.源程序代码:#include<iostream>using namespace std;const double PI=3.14159;class point //定义point类{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<<","<<y<<") ";}};class circle:public point //公有继承point类,派生出circle类{protected:double radius;public:circle(){x=0;y=0;radius=0;}circle(double xv,double yv,double vv):point(xv,yv){radius=vv;}circle(point p,double vv):point(p){radius=vv;}circle(circle &cir):point(cir){radius=cir.radius;}double area(){return PI*radius*radius;}void show(){point::show();cout<<"radius="<<radius<<endl;}};class cylinder:public circle //公有继承circle类,派生出cylinder类{protected:double high;public:cylinder(){x=0;y=0;radius=0;high=0;}cylinder(double xv,double yv,double vv,double hv):circle(xv,yv,vv) {high=hv;}cylinder(cylinder &cyl):circle(cyl){high=cyl.high;}double area(){return(2*PI*radius*high+2*circle::area());}void show(){cout<<"圆柱体信息:"<<endl;circle::show();cout<<"high="<<high<<endl;}};int main() //主函数的定义{point point1(2,5);circle circle1;circle circle2(1,2,3);circle circle3(point1,4);circle1.show();circle2.show();circle3.show();cylinder cylinder1(5,6,11,20);cylinder1.show();cout<<"圆柱体面积:"<<cylinder1.area()<<endl; }实验截图:[实验体会]1、掌握类的继承与派生的实现方法;2、定义合适的派生类构造函数,用于初始化基类成员和对象成员;3、要理解赋值兼容性原则,掌握派生类的复制构造函数的定义方法;4、在派生类中可以通过基类名调用基类的成员。

继承与派生实验报告

继承与派生实验报告

继承与派生实验报告继承与派生实验报告引言:继承与派生是面向对象编程中的重要概念,通过继承,一个类可以派生出子类,从而实现代码的复用和扩展。

本文将通过实验来探讨继承与派生的概念、原理和应用。

实验目的:1. 理解继承与派生的概念和原理;2. 掌握如何在编程语言中实现继承和派生;3. 熟悉继承与派生的应用场景。

实验步骤:1. 创建父类:首先,我们创建一个名为"Animal"的父类,该类具有属性和方法,例如"age"和"eat()"。

2. 创建子类:接下来,我们创建一个名为"Cat"的子类,该类继承自"Animal"类。

在子类中,我们可以重写父类的方法或添加新的方法。

3. 实例化对象:通过实例化父类和子类的对象,我们可以调用它们的方法和访问它们的属性。

4. 测试继承与派生:我们可以通过调用父类和子类的方法,观察它们的行为是否符合预期。

实验结果:在创建父类"Animal"时,我们定义了一个"age"属性和一个"eat()"方法。

在创建子类"Cat"时,我们继承了父类的属性和方法,并添加了一个新的"meow()"方法。

在实例化父类对象时,我们可以通过调用"eat()"方法来模拟动物进食的行为。

而在实例化子类对象时,我们既可以调用从父类继承而来的"eat()"方法,也可以调用子类特有的"meow()"方法来模拟猫咪的叫声。

通过实验,我们发现继承与派生的优势在于代码的复用和扩展。

我们只需在父类中定义一次通用的属性和方法,然后让不同的子类继承父类,即可实现代码的复用。

同时,子类还可以通过重写父类的方法或添加新的方法,实现代码的扩展和个性化。

讨论与应用:继承与派生不仅仅局限于上述的父类和子类关系,它还可以在多层次的继承结构中发挥作用。

《继承和派生》课件

《继承和派生》课件
时提供默认值。
派生类的析构函数
派生类析构函数在销毁派生类对象时 自动调用,用于释放派生类所占用的 资源。
派生类析构函数可以包含代码,用于 清理派生类所占用的资源。
派生类析构函数可以访问基类的析构 函数,通过使用`this`关键字调用基类 析构函数。
派生类析构函数可以重载基类析构函 数,以便在销毁派生类对象时执行特 定的操作。
基类析构函数的调用
在派生类的析构函数中,可以通过使用`this`关键字调 用基类的析构函数,以确保基类资源得到正确释放。
输标02入题
如果在派生类的析构函数中没有显式调用基类的析构 函数,则编译器会自动调用基类的默认析构函数。
01
03
在某些情况下,可能需要显式调用基类的析构函数, 以确保资源得到正确释放。例如,当基类包含动态分
02 继承的方式
公有继承
总结词
公有继承是指子类可以访问父类的公有成员。
详细描述
在公有继承中,子类可以访问父类的公有成员(即不加任 何修饰符的成员),这些成员在子类中保持公有属性。子 类可以继承和使用父类的公有成员,包括函数、变量、常 量等。
总结词
公有继承是实现代码复用的一种方式。
详细描述
通过公有继承,子类可以继承父类的公有成员,从而避免 重复编写相同的代码。这有助于提高代码的复用性和维护 性。
注意事项
虚函数和纯虚函数的使用 应合理规划,避免过度使 用导致程序复杂度和维护 成本增加。
继承和派生的效率问题
继承
通过共享已存在的代码, 减少代码冗余。但也可能 导致内存浪费和性能下降 。
派生
通过扩展已有类,增加新 功能或修改已有功能。但 也可能导致内存消耗增加 和性能下降。
注意事项

实验四 C++中的继承与派生

实验四  C++中的继承与派生

实验四C++中的继承与派生一、实验目的:1.理解C++中继承与派生的概念;2.掌握C++中各种不同继承方式的访问属性差别;3.掌握单继承与多继承的实现方法;4.掌握派生类构造函数与析构函数的实现及调用顺序;5.掌握虚基类的使用方法。

二、实验任务【题目】小型公司人员管理某小型公司有四类人员:经理、技术人员、销售经理、销售员。

设计一个基类employee,派生出manager(经理)、technician(技术人员)、salesmanager(销售经理)、saleman(销售员)。

销售经理既是经理又是销售员,兼具两类人员的特点,因此同时继承manager 和salesman 两个类。

1、类定义1)employee 类:基本信息:编号、姓名、性别、出生日期、职位、薪水等;出生日期使用自定义的Date (日期)类;2)Date 类:成员变量:年、月、日3)派生类technician:新增属性:工作时间派生类saleman:新增属性:销售额、所属部门2、实现人员信息的录入与显示;3、计算并显示个人月薪:月薪计算办法:总经理拿固定月薪8000 元,技术人员按每小时25 元领取月薪;推销员的月薪按当月销售额的4%提成;销售经理固定月薪5000 元加所管辖部门当月销售总额的5‰。

【提示】1、在基类中,除了定义构造函数和析构函数,还应统一定义对各类人员信息应有的操作,规范类族中各派生类的基本行为,但是各类人员的月薪计算方法不同,不能在基类employee 中统一确定计算方法。

各类人员信息的显示内容不同,同样不能在基类employee中统一确定显示方法。

在基类中实现上述功能的函数体应为空,在派生类中根据同名覆盖原则定义各自的同名函数实现具体功能。

代码:#include<iostream>#include<string>using namespace std;class Date{private:int year;int month;int day;public:void SetYear(int x) {year=x;}void SetMonth(int x) {month=x;}void SetDay(int x) {day=x;}int GetYear() {return year;}int GetMonth() {return month;}int GetDay() {return day;}};class employee{protected:int num;string nam;string sex;Date birth;string position ;float salary;public:void display(){cout<<"编号:"<<num<<"姓名:"<<nam<<"性别:"<<sex<<"出生日期:"<<birth. GetYear()<<"-"<<birth.GetMonth()<<"-"<<birth.GetDay()<<"职位:"<<position;}};class manager:virtual public employee{public:void set_manager(int n,string na,string se,int y,int m,int d,string pos){num=n;nam=na;sex=se;birth.SetYear(y);birth.SetMonth(m);birth.SetDay(d);position=pos;}void display(){employee::display();}void total_salary(){ salary=8000;cout<<"经理月薪:";cout<< salary<<"元";}};class technician:virtual public employee{protected:float Time;public:float t;void set_technician(int n,string na,string se,int y,int m,int d,string pos,float t) { num=n;nam=na;sex=se;birth.SetYear(y);birth.SetMonth(m);birth.SetDay(d);position=pos;Time=t;}void display(){ employee::display();cout<<"工作时间:"<<Time<<endl;}void total_salary(){salary= 25*Time;cout<<"技术人员月薪:" ;cout<< salary<<"元";}};class saleman :virtual public employee{protected:float sale;string dep;public:void set_saleman(int n,string na,string se,int y,int m,int d,string pos,float sale1,string de) {num=n;nam=na;sex=se;birth.SetYear(y);birth.SetMonth(m);birth.SetDay(d);position=pos;sale=sale1;dep=de;}void display(){employee::display();cout<<position<<"销售额:"<<sale<<"所属部门:"<<dep<<endl;}void total_salary (){salary=sale*0.04;cout<<"销售员月薪:"<<salary<<"元";}};class salesmanager:public manager,public saleman{public:void total_salary (){salary=sale*0.05+5000;cout<<"销售经理月薪:" << salary<<"元";}};int main (){manager m1;technician tec;saleman s;salesmanager sg;int n,y,m,d,choose,choose1;string str,se, p;cout<<"\n\t\t================================================="<<endl;cout<<"\t\t1:输入信息与显示2:个人月薪0:退出"<<endl;cout<<"\t\t=================================================="<<endl;cout<<"\n输入您要进行的操作:";cin>>choose;while(choose!=0){switch(choose){case 1:cout<<"输入员工编号:";cin>>n;cout<<"输入员工出生日期:";cin>>y>>m>>d;cout<<"输入员工姓名:";cin>>str;cout<<"输入员工性别:";cin>>se;cout<<"输入员工职位:";cin>>p;if (p=="manager"){m1.set_manager( n, str, se,y,m,d,p);m1.display();}else if(p=="technician"){float t;cout<<"输入时间:";cin>>t;tec.set_technician( n,str, se,y,m,d, p, t) ;tec.display();}else if(p=="saleman"){float sale2;string de;cout<<"销售额:" ;cin >> sale2;cout<<"所属部门:";cin>>de ;s.set_saleman( n, str, se,y,m,d, p, sale2, de);s.display();}else{float sale1;string de;cout<<"销售额:" ;cin>>sale1;cout<<"所属部门:";cin>>de ;sg.set_saleman( n,str, se,y,m,d, p, sale1, de) ;s.display();}break;case 2:cout<<"\n\t\t===================================================="<<endl;cout<<"\t\t11: 经理12: 技术人员13:销售员14:销售经理"<<endl;cout<<"\t\t============================================================"< <endl;cout<<"\n输入您要进行的操作:";cin>>choose1;while(choose1!=0){ switch(choose1){case 11:m1.total_salary();break;case 12:tec.total_salary();break;case 13:s.total_salary();break;case 14:sg.total_salary();break;}choose1=0;}break;}cout<<"\n\t\t=================================================="<<endl;cout<<"\t\t1:输入信息与显示2:个人月薪0:退出"<<endl;cout<<"\t\t=================================================="<<endl;cout<<"\n输入您要进行的操作:";cin>>choose;}return 0;}。

C 继承与派生实验报告

C 继承与派生实验报告

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;}上述代码示例了如何使用派生类创建对象,并访问基类的属性和派生类自己的属性。

实验4 派生与继承

实验4  派生与继承

实验4 派生与继承一、实验目的理解继承思想,掌握继承的语法,体会不同继承方式下派生类对基类成员的访问权限。

二、实验内容:1.编写一个程序,实现字符串的相关操作。

要求:在已有简单串类myString的基础上派生字符串类String1,类中包含输入字符串、返回字符串长度及内容等功能,并能实现字符串连接与比较(不用库函数);设计一个具有编辑功能的串类String2,它从String1类派生而来。

成员函数能够在在字符串指定位置处实现如下操作:插入字符串、替换和删除某个字符,并能查找子串。

类的设计可参考如下UML图:2. 综合性的实验,设计数组类族。

要求编写的程序涉及到C++的许多知识点,如类的定义,动态分配内存,构造函数,派生,虚基类等。

实验内容给出的是一个完整的程序,4个题目实际是类等级。

同学也可以在此基础上发挥增加新的内容。

(1)定义一个基类MyArray,基类中可以存放一组数组。

Class Myarray{ int *alist;int length;public:Myarray( int leng);Myarray(const Myarray&);~myarray();void input();void display();};编写构造函数,析构函数及其它函数,实现动态分配内存,释放内存和数据输入输出等功能。

并进行调试。

(2)定义一个类averarray继承自myarray,在类中求数组的平均值,并输出。

进行调试。

(3)定义一个类revarray继承自myarray, 使数组按反序存放,并输出。

进行调试。

(4)定义一个类Safearray继承自averarray和revarray,并保证访问数组不会越界。

在继承过程中声明为虚基类,体会虚基类在解决二义性中的问题中的作用。

调试中可以试一试不用虚基类出现的问题。

(提交书面作业)3. 设计一个学生和教师类,学生数据有编号、姓名、班级和成绩;教师数据有编号、姓名、职称和部门;要求:运用继承的思想实现相关功能:对学生和教师的数据进行输入和显示,类中包括各种构造函数,思考如何在派生类的构造函数中初始化基类的成员。

继承与派生

继承与派生

实验四继承与派生一.实验目的及要求1.掌握单继承和多重继承下派生类的定义方法,理解基类成员在不同的继承方式下不同的访问属性。

2.正确定义派生类的构造函数与析构函数,理解定义一个派生类对象时各个构造函数、析构函数被调用的顺序。

3.正确定义虚基类,消除在多层次继承方式下顶层基类中成员访问的二义性问题,关注此时各构造函数、析构函数的调用顺序。

4.通过基类与派生类的定义,及基类对象、指针、引用与派生类的对象、地址间相互赋值的方法,正确理解赋值兼容的4种情况,通过程序理解其不可逆性。

二.实验内容在自己的文件夹下建立一个名为exp4的工程,在该工程中做如下操作:定义一个车基类,派生出自行车类和汽车类,又以自行车类和汽车类为基类共同派生出摩托车类,每个类都要定义带有参数的构造函数。

对自行车类继承基类的方式分别用private、protected、public,观察基类成员在派生类中的访问属性;观察自行车类、汽车类和摩托车类对象定义时构造、析构函数的调用顺序。

最后将车基类定义为虚基类再观察程序运行结果,具体完成以下要求。

(1)定义基类Vehicle,具有两个保护成员变量:MaxSpeed、Weight,有3个公有的成员函数:Run()、Stop()、Show(),以及带参数构造函数、析构函数;再定义一个从Vehicle公有继承的Bicycle类,增加Height保护属性的成员变量,定义Bicycle类的构造函数、析构函数,改造Show函数,用于输出本类中的完整信息。

main()函数中定义Bicycle类对象,观察构造函数和析构函数的执行顺序,以及各成员函数的调用。

请用跟踪的方法观察程序运行的每一步究竟调用的是哪一个函数。

(2)在上一步基础上,将继承方式分别修改为protected和private,再重新编译,观察这时的报错信息并能解释。

修改程序使程序正确运行。

(3)将Bicycle类的继承方式恢复为public,代码回到(1)的状态,再在Bicycle类下面增加一个第二层汽车类Car的定义,Car也是公有继承基类Vehicle,其中增加了一个保护成员变量SeatNum,表示汽车有几个座位,其定义方式与类Bicycle类似。

实验4 继承与派生

实验4  继承与派生

实验4 继承与派生班级网络1311 学号39 姓名付豪成绩一、实验目的1.熟练掌握类的继承,能够定义和使用类的继承关系2.掌握派生类的声明与实现方法3.掌握类构造函数的初始化列表与作用域分辨率的使用方法4.理解虚基类在解决二义性问题中的作用.二、实验内容1.定义一个基类有姓名、性别、年龄,再由基类派生出教师类和学生类,教师类增加工号、职称和工资,学生类增加学号、班级、专业和入学成绩,在main()函数中定义基类和派生类对象,对类进行测试。

2.声明一个哺乳动物Mammal类,再由此派生出狗Dog类,声明一个Dog类的对象,观察基类与派生类的构造函数与析构函数的调用顺序。

3.定义一个Point类,派生出矩形类Rectangle和圆类Circle,计算各派生类对象的面积Area()。

4.设计一个圆类circle和一个桌子类table,另设计一个圆桌类roundtable,它是从前两个类派生的,要求输出一个圆桌的高度、面积和颜色等数据。

5.定义一个大学生类student,函数私有数据成员:姓名、学号、校名,并为它定义带参数的构造函数,参数带缺省值的构造函数和输出数据成员值的print()公有成员函数,另定义研究生类,它以公有继承方式派生于类student,新增加“研究方向、导师名”两个私有数据成员,并定义带参数的构造函数和输出研究生数据的print()公有成员函数。

在main()函数中定义基类和派生类对象,对类进行测试。

三、实验源程序、测试与结论1.#include<iostream>#include<string>using namespace std;class person{string name; char sex;int age;public:person(string n,char s,int a):name(n),sex(s),age(a) {}void show(){cout<<name<<endl;cout<<sex<<endl;cout<<age<<endl;}};class teacher:public person{int num; string job; int money;public:teacher(string n,char s,int a,int nu,string j,int m):person(n,s,a),num(nu),job(j),money(m) {} void show(){person::show();cout<<num<<endl;cout<<job<<endl;cout<<money<<endl;}};class student:public person{int num; string Class; string zhuanye; float sorce;public:student(string n,char s,int a,int nu,string C,string z,float ss):person(n,s,a),num(nu),Class(C),zhuanye(z),sorce(ss) {}void show(){person::show();cout<<num<<endl;cout<<Class<<endl;cout<<zhuanye<<endl;cout<<sorce<<endl;}};void main(){ teacher t1("Fsda",'M',1234,74,"jiaoshi",8000);student s1("Hfgh",'F',1145,1001,"BX1311","wangluo",511);t1.show();cout<<endl<<endl;s1.show();}2.#include<iostream>using namespace std;class Mammal{public:Mammal(){cout<<"Mammal构造"<<endl;}~Mammal(){cout<<"Mammal析构"<<endl;} };class Dog:public Mammal{public:Dog(){cout<<"Dog构造"<<endl;}~Dog(){cout<<"Dog析构"<<endl;} };void main(){ Dog a;}3.#include<iostream>using namespace std;class Point{double x;double y;public:Point(double x,double y):x(x),y(y){}void show(){cout<<"("<<x<<","<<y<<")"<<endl;}};class Rectangle:public Point{double x, y;public:Rectangle(double x,double y,double x1,double y1):Point(x,y),x(x1),y(y1){}void Area(){Point::show();cout<<"Ãæ»ý:"<<x*y<<endl;}};class Circle:public Point{double r;public:Circle(double x,double y,double c):Point(x,y),r(c){}void Area(){ Point::show();cout<<"Ãæ»ý:"<<r*r*3.14<<endl;}};void main(){Rectangle f2(5,6,7,8);Circle f3(1,2,3);f2.Area();f3.Area();}4.#include<iostream>#include<string>using namespace std;class Circle{int r;public:Circle(int r1){r=r1;}};class Table{int h;string color;public:Table(int h1,string c1){h=h1;color=c1;}};class Roundtable:public Circle,public Table{public:Roundtable(int x,int y,string z):Circle(x),Table(y,z){cout<<"高度:"<<x<<"面积:"<<y<<"颜色:"<<z<<endl;}};void main(){ string c;cout<<"请输入颜色:"<<endl;cin>>c;Roundtable a(7,11,c);}5.#include<iostream>#include<string>using namespace std;class student{protected:string name;int num;string school;public:student(string n="hi",int a=0,string b="bey"):name(n),num(a),school(b){} void print(){ cout<<"name:"<<name<<endl;cout<<"num:"<< num<<endl;cout<<"school:"<<school<<endl;}};class graduate:public student{string research_area;string tutor_name;public:graduate(string a,int b,string c,string d,string e):student(a,b,c),research_area(d),tutor_name(e){}void print(){ cout<<"name:"<<name<<endl;cout<<"num:"<< num<<endl;cout<<"school:"<<school<<endl;/**///student::print();cout<<"research_area:"<<research_area<<endl;cout<<"tutor_name:"<<tutor_name<<endl;}};void main(){graduate g("Fsda",17,"DJ","wangluo","Tao");cout<<"graduate:"<<endl;g.print();cout<<endl<<endl;student s("Fuh",11,"DJ");cout<<"student:"<<endl;s.print();}四、实验小结能够较好地应用类的继承,能够定义和使用类的继承关系掌握了派生类的声明与实现方法对类构造函数的初始化列表与作用域的使用更加熟悉理解虚基类在解决二义性问题中的作用.。

《继承和派生》PPT课件

《继承和派生》PPT课件

完整版ppt
15
继承和派生
练习、设计一个圆类,从圆派生圆柱(或圆 锥),并设计成员函数输出圆柱(或圆锥) 的底面面积和体积。
完整版ppt
16
继承关系中构造函数之间的关系
• 派生类不继承基类的构造函数 • 派生类和基类的构造函数之间是一种自动调用的
关系 • 创建派生类对象时,派生类构造函数要调用基类
成员M基类中的存取权 成员M 在private继承后

的派生类的存取权限
public
private
protected
private
private
隐藏
完整版ppt
12
受保护继承(protected)和派生
• 基类中公有成员和受保护成员被继承后都是受 保护的
成员M基类中的存取权限 成员M 在protected继承后 的派生类的存取权限
性和行为 • 派生类可以修改继承的属性和行为 • 派生类可以增加新的属性和行为 • 派生类对象也是基类对象 • 派生类对象和基类对象可以被统一管理
完整版ppt
4
继承和派生的基本概念
基类
数据成员 函数成员
派生类
基类
数据成员 函数成员
自己的数据成员 自己的函数成员
完整版ppt
5
继承的意义
• 便于管理系统中的对象 • 系统扩充比较容易- 利用程序代码的再用性
继承和派生
继承和派生的基本概念 单一继承定义 派生类重定义基类函数 基类中成员被继承后存取权限等级的变化 继承关系中构造函数、析构函数之间的关
系 多重继承
完整版ppt
1
继承的例子
• 家具和柜子 • 建筑和房子 • 道路和高速公路 • 动物和猫 • 电视和彩色电视 • 电脑和笔记本电脑

继承与派生类知识要点

继承与派生类知识要点

继承与派生类知识要点1.1.掌握继承和派生的定义,派生类的定义方法。

(1)掌握继承的两种类型:单继承和多继承。

(2)掌握private,public,protected三种继承方式的特点。

继承方式决定了基类中的成员在派生类中的属性。

三种继承方式的共同点:基类的private成员在派生类中不可见。

区别:对于私有继承,基类的public、protected成员在派生类中作为private成员;对于公有继承,基类的public、protected成员在派生类中访问属性不变;对于保护继承,基类的public、protected成员在派生类中作为protected成员。

(3)掌握派生类中的构造函数和析构函数的使用。

基类的构造函数和析构函数不能继承,所以必要时在派生类中定义自己的构造函数和析构函数。

派生列的构造函数完成基类中新增数据成员和基类数据成员的初始化,基类数据成员的初始化通过基类构造函数来实现。

(4)掌握派生类的同名覆盖规则。

(5)掌握赋值兼容规则。

基类对象可以使用公有派生类对象来代替,包括:派生类对象可以赋值给基类对象;派生类对象可以初始化基类对象的引用;基类类型指针可以指向派生类对象。

2.2.掌握多重继承的概念、定义方法、多重继承派生类构造函数的执行顺序。

派生类构造函数的执行顺序是先执行所有基类的构造函数(顺序按照定义派生类时指定的各基类顺序),在执行对象成员所在类的构造函数(顺序按照他们在类中的声明顺序),最后执行派生类构造函数体中的内容。

3.3.掌握虚基类的概念和定义方法。

在多重继承中,如果多条继承路径上有一个公共的基类,则在这些路径的汇合点上的派生类会产生来自不同路径的公共基类的多个拷贝,如果用virtual把公共基类定义成虚基类,则只会保留公共基类的一个拷贝。

C 继承与派生实验报告

C  继承与派生实验报告

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,我们可以看到其对程序运行结果的影响。

这种灵活性,使得我们可以根据具体需求,定制不同的派生类,实现更加个性化的功能。

实验四 继承与派生2

实验四 继承与派生2

实验四继承与派生(二)班级:软件1302班学号:201313138064 姓名:代永强[实验目的]:1.理解多重继承的概念;2.理解为了避免同一基类出现多个重复的副本而采用的虚基类概念和虚拟继承;3.学习利用虚基类解决二义性问题。

[实验内容]:实验题目:设计一个用于人事管理的“people(人员)”基类。

考虑到通用性,仅抽象出所有类型人员都具有的属性:编号、姓名、性别、出生日期、身份证号等;从people(人员)类派生出student(学生)类,并添加属性:班号ClassNo;从people类派生出teacher(教师)类,并添加属性:专业subject、导师teacher adviser(teacher类);从graduate 类和teacher类派生出TA(助教生)类。

设计时注意虚基类的使用,注意重载相应的成员函数。

测试这些类。

程序源代码:#include<iostream>#include<string>using namespace std;class Date{private:int Year;int Month;int Day;public:Date();Date(int Y,int M,int D);void SetDate(int y,int m,int d);int GetYear(){return Year;}int GetMonth(){return Month;}int GetDay(){return Day;}virtual ~Date();};Date::Date(){Year=0;Month=0;Day=0;}Date::Date(int Y,int M,int D){Year=Y;Month=M;Day=D;}void Date::SetDate(int y,int m,int d){Year=y;Month=m;Day=d;}Date::~Date(){}class people{private:string Num;string Name;string Sex;Date birthday;string Id;public:people();people(string num,string name,string sex,int y,int m,int d,string id);people(people &p);string GetName();void Show();virtual ~people();};people::people(){}people::people(string num,string name,string sex,int y,int m,int d,string id):birthday(){birthday.SetDate(y,m,d);Num=num;Name=name;Sex=sex;Id=id;}people::~people(){}people::people(people &p):birthday(p.birthday){Num=p.Num;Name=;Sex=p.Sex;Id=p.Id;}void people::Show(){cout<<"编号:"<<Num<<endl;cout<<"姓名:"<<Name<<endl;cout<<"性别:"<<Sex<<endl;cout<<"出生日期:"<<birthday.GetYear()<<"-"<<birthday.GetMonth()<<"-"<<birthday.GetDay()<<endl;cout<<"身份证号:"<<Id<<endl;}string people::GetName(){return Name;}class student:virtual public people{private:int ClassNo;public:student(people p,int c);student(student &s);void Show();virtual ~student();};student::student(people p,int c):people(p){ClassNo=c;}student::student(student &s):people(s){ClassNo=s.ClassNo;}student::~student(){}void student::Show(){people::Show();cout<<"班号:"<<ClassNo<<endl;}class teacher:virtual public people{private:string Principalship;string Department;public:teacher(people p,string pr,string de);teacher();teacher(teacher &t);void Show();virtual ~teacher();string GetPrincipalship();string GetDepartment();};teacher::teacher(people p,string pr,string de):people(p){Principalship=pr;Department=de;}teacher::teacher():people(){Principalship=" ";Department=" ";}teacher::teacher(teacher &t):people(t){Principalship=t.Principalship;Department=t.Department;}string teacher::GetPrincipalship(){return Principalship;}string teacher::GetDepartment(){return Department;}void teacher::Show(){people::Show() ;cout<<"职务:"<<Principalship<<endl;cout<<"部门:"<<Department<<endl;}teacher::~teacher() {}class graduate:public student{protected:string Subject;teacher adviser;public:graduate(teacher t,people p1,int c,string su);void Show();virtual ~graduate();};graduate::graduate( teacher t,people p1,int c,stringsu ):people(p1),adviser(t),student(p1,c){Subject=su;}void graduate::Show(){student::Show();cout<<"专业:"<<Subject<<endl;cout<<"导师:"<<adviser.GetName()<<endl;;}graduate::~graduate(){}class TA:virtual public graduate,virtual public teacher{public:TA( teacher t1,people p,string su,int c,string pr,string de);void Show();private:teacher t;};TA::TA(teacher t1,people p,string su,int c,string pr,string de):people(p),graduate(t1,p,c,su),teacher(p,pr,de){}void TA::Show(){graduate::Show();cout<<"职务:"<<teacher::GetPrincipalship()<<endl;cout<<"部门:"<<teacher::GetDepartment()<<endl;}int main(){cout<<"Student:"<<endl;people a1("001","小明","男",1990,2,28,"201313138064");student b(a1,30) ;b.Show();cout<<endl;cout<<"Teacher:"<<endl;people a2("002","小红","女",1991,5,12,"201313138065");teacher c(a1,"助教","武汉科技大学");c.Show();cout<<endl;cout<<"Graduate:"<<endl;people a3("003","小李","男",1990,4,28,"201313138066");graduate d(c,a3,30,"软件工程");d.Show();cout<<endl;cout<<"TA:"<<endl;people a4("004","老王","男",1980,7,8,"2198080808067");TA e(c,a4,"软件工程",30,"教授","武汉科技大学");e.Show();return 0;}程序运行结果:UML图:。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验四继承与派生实验四派生类与继承【实验类型】验证性实验【实验课时】2学时【实验目的】(1)理解类的继承的概念,能够定义和使用类的继承关系。

(2)掌握派生类的声明与定义方法。

(3)熟悉公有派生和私有派生的访问特性。

(4)学习虚基类在解决二义性问题中的作用。

【实验环境】硬件:计算机软件:Microsoft Visual C++ 6.0【实验内容】1、按要求阅读、编写、调试和运行以下程序。

(1)实验内容①定义一个基类MyArray,基类中可以存放一组整数。

class MyArray{public:MyArray(int leng);~MyArray();void Input();void Display();protected:long int *alist; // 指向动态申请的一组空间int length;}; // 整数的个数基类中有构造函数、析构函数、输入数据和输出数据的函数。

②定义一个类SortArray继承自MyArray ,在该类中定义函数实现排序功能。

③定义一个类ReArray继承自MyArray ,在该类中定义函数实现逆转功能。

④定义一个类AverArray继承自MyArray ,在该类中定义函数Aver求解整数的平均值。

⑤定义NewArray类,同时继承了SortArray, ReArray和AverArray,使得NewArray类的对象同时具有排序、逆转、和求平均值的功能。

在继承的过程中声明为虚基类,体会虚基类在解决二义性问题中的作用。

(2)实验程序 (参考)程序如下:#include "iostream.h"#include "process.h"class MyArray{public:MyArray(int leng);~MyArray();void Input();void Display();protected:long int *alist; // 指向动态申请的一组空间int length; // 整数的个数};MyArray::MyArray(int leng){ length=leng;alist=new long int[length];if(alist==NULL){cout<<"对不起,创建失败。

请重试。

";exit(1);}}MyArray::~MyArray(){delete[] alist;cout<<"数组被清空。

"<<endl;}void MyArray::Display() // 显示数组内容{int i;long int *p=alist;for (i=0;i<length;i++,p++)cout<<" "<<*p;}void MyArray::Input() // 从键盘若干整数{cout<<"请输入:"<<length<<"个整数:";int i;long int *p=alist;for(i=0;i<length;i++,p++)cin>>*p;}class SortArray: virtual public MyArray{private:int len;long int *sp;public:SortArray(int leng):MyArray(leng){len=leng;Sort();};void Sort(){sp=new long int[len];long int q;sp=alist;for(int i=0;i<len;i++){for(int j=0;j<len-1;j++){if(*(sp+j)>*(sp+j+1)){q=*(sp+j);*(sp+j)=*(sp+j+1);*(sp+j+1)=q;}}}}};class ReArray: virtual public MyArray {// 这里是虚基类,public:void Reverse(){rp=new long int[len];long int q;rp=alist;for(int i=0;i<len/2;i++){q=*(rp+i);*(rp+i)=*(rp+len-i-1);*(rp+len-i-1)=q;}}ReArray(int leng):MyArray(leng){len=leng;Reverse();}private:int len;long int *rp;};class AverArray:virtual public MyArray{ // 这里是虚基类,public:double Aver(){ap=new long int[len];double q=0;ap=alist;for(int i=0;i<len;i++){q=q+*ap;ap++;}q=q/len;return q;}AverArray(int leng):MyArray(leng){len=leng;}private:int len;long int *ap;};class NewArray:public ReArray,public SortArray,public AverArray { public:NewArray(int leng);~NewArray();};NewArray::NewArray(intleng):MyArray(leng),SortArray(leng),ReArray (leng),AverArray(leng){cout<<"\n新数组正在创建。

\n";}NewArray::~NewArray(){cout<<"\n新数组已被清空。

\n";}void main(){char b;int leng;do{cout<<"请输入数组长度:"<<endl;cin>>leng;while(leng<=0){cout<<"数组长度必须为大于零的整数,请重新输入数组长度:\n";exit(1);cin>>leng;}cout<<"\n开始:\n";NewArray n(leng);n.Input();cout<<"\n您输入的数组为:"<<endl;n.Display(); // 显示数组n.Reverse(); //显示逆序cout<<"\n倒序数组为:"<<endl;n.Display(); // 显示逆转以前的情况cout<<"\n平均值是:"<<n.Aver()<<endl;//求平均值n.Sort(); //排序cout<<"\n排序后(从小到大)数组为:"<<endl;n.Display(); // 显示排序以后的情况cout<<"\n[A]继续 [Q]退出"<<endl;cin>>b;}while(b=='A'||b=='a');}执行结果为:2、编写一个学生和教师数据输入和显示程序。

(1)实验内容编写学生和教师数据输入和显示程序,学生数据有编号、姓名、班号和成绩,教师数据有编号、姓名、职称和部门。

要求将编号、姓名输入和显示设计成一个类person,并作为学生数据操作类student和教师数据操作类teacher 的基类。

(2)实验程序(参考)#include<iostream.h>class person{protected:int m;char A[20];char *name;public:void input(){cout<<"编号:";cin>>m;cout<<"姓名:";cin>>A;name=&A[0];}void display(){cout<<"编号:"<<m<<endl;cout<<"姓名:"<<name<<endl;}};class student:public person{protected:int classnum, mark;public:void input1(){cout<<"输入一个学生数据:"<<endl;input();cout<<"班号:";cin>>classnum;cout<<"成绩:";cin>>mark;}void display1(){cout<<"显示一个学生的数据:"<<endl;display();cout<<"班号:"<<classnum<<endl;cout<<"成绩:"<<mark<<endl;}};class teacher: public person{protected:char zhicheng[20],bumen[20];char *p;public:void input2(){cout<<"显示一个老师的数据:"<<endl;input();cout<<"职称:";cin>>zhicheng;cout<<"部门:";cin>>bumen; }void display2(){cout<<"显示一个老师的数据:"<<endl;display();p=&zhicheng[0];cout<<"职称:"<<p<<endl;p=&bumen[0];cout<<"部门:"<<p<<endl;}};void main(){student S;teacher T;S.input1();T.input2();S.display1();T.display2();}【实验提示】继承是面向对象程序设计的一个重要特性,它允许在已有类的基础上创建新的类,新类可以从一个或多个既有类中继承函数和数据,而且可以重新定义或加进新的数据和函数,从而形成类的层次或等级。

相关文档
最新文档