C++语言程序设计实验答案_继承与派生
- 格式:doc
- 大小:246.50 KB
- 文档页数:15
第8章习题一、概念题1.解答要点如下。
⑴采用public公有派生,基类成员的访问权限在派生类中保持不变,即基类所有的公有或保护成员在派生类中仍为公有或保护成员。
public派生最常用,可以在派生类的成员函数中访问基类的非私有成员,可通过派生类的对象直接访问基类的公有成员。
⑵采用private私有派生,基类所有的公有和保护成员在派生类中都成为私有成员,只允许在派生类的成员函数中访问基类的非私有成员。
private派生很少使用。
⑶采用protected保护派生,基类所有的公有和保护成员在派生类中都成为保护成员,只允许在派生类的成员函数和该派生类的派生类的成员函数中访问基类的非私有成员。
2.解答要点如下。
派生类构造函数的执行次序:首先,调用基类构造函数,调用顺序按照它们被继承时声明的基类名顺序执行;其次,调用内嵌对象构造函数,调用次序为各个对象在派生类内声明的顺序;最后,执行派生类构造函数体中的内容。
派生类析构函数执行过程与构造函数执行过程相反。
即当派生类对象的生存期结束时,首先调用派生类的析构函数,然后调用内嵌对象的析构函数,再调用基类的析构函数。
3.解答要点如下。
在多重继承中,如果多条继承路径上有一个公共的基类,则在这些路径的汇合点上的派生类会产生来自不同路径的公共基类的多个拷贝,如果用virtual把公共基类定义成虚基类,则只会保留公共基类的一个拷贝。
引进虚基类的目的是为了解决二义性问题,使得公共基类在它的派生类对象中只产生一个基类子对象。
二、填空题1.派生类基类2.public、protected、private3.virtual4.基类派生类自身5.成员函数三、编程题1.#include<iostream.h>#include<string.h>#include<iomanip.h>class base //定义一个基类{protected:char name[20]; //姓名char sex[3]; //性别int age; //年龄…};class teacher:public base //基类派生出教师类{ int sno; //工号char zc[20]; //职称double wages; //工资…};class student :public base //基类派生出学生类{ int sno; //学号char bj[10]; //班级char zy[10]; //专业double score; //入学成绩…};2.class Shape{public:virtual float area()=0;};float total(Shape *s[],int n){float sum=0.0;for(int i=0;i<n;i++)sum+=s[i]->area();return sum;}class Triangle:public Shape{public:Triangle(double h,double w){H=h;W=w;}double area() const{return H*W*0.5;}private:double H,W;};class Rectangle:public Shape{public:Rectangle(double h,double w){H=h;W=w;}double area()const{return H*W;}private:double H,W;};3.#include<iostream.h>class Vehicle{protected:int wheels;double weight;public:void initialize(int whls, double wght);int get_wheels() { return wheels; }double get_weight() { return weight; }double wheel_loading() { return weight/wheels; }};class Car:public Vehicle{private:int passenger_load;public:void initialize(int whls, double wght, int people =4);int passengers() { return passenger_load; }};class Truck: public Vehicle{private:int passenger_load;double payload;public:void init_truck(int number =2, double max_load =24000.0);double efficiency();int passengers() { return passenger_load; }};void Vehicle::initialize(int whls, double wght){wheels=whls;weight=wght;}void Car::initialize(int whls, double wght, int people){wheels=whls;weight=wght;passenger_load=people;}void Truck::init_truck(int number, double max_load){passenger_load=number;payload=max_load;}double Truck::efficiency(){return payload/(payload+weight);}void main(){Vehicle bicycle;bicycle.initialize(2,25);cout<<"the bicycle has "<<bicycle.get_wheels()<<" wheels.\n";cout<<"the bicycle weighs "<<bicycle.get_weight()<<" pounds.\n";cout<<"the bicycle's wheel loading is "<<bicycle.wheel_loading()<<" pounds per tire.\n\n";Car audi;audi.initialize(4,3500.0,5);cout<<"the audi has "<<audi.get_wheels()<<" wheels.\n";cout<<"the audi weighs "<<audi.get_weight()<<" pounds.\n";cout<<"the audi's wheel loading is "<<audi.wheel_loading()<<" pounds per tire.\n\n";Truck jief;jief.initialize(18,12500.0);jief.init_truck(2,33675.0);cout<<"the jief has "<<jief.get_wheels()<<" wheels.\n";cout<<"the jief weighs "<<jief.get_weight()<<" pounds.\n";cout<<"the jief's efficiency is "<<100.0*jief.efficiency()<<" percent.\n";}。
第四章继承与派生1、填空题1)在派生类中使用基类的成员,可以显示地使用___成员名限定符__来使用基类成员。
2)垂直访问时,保护成员的访问控制权限与____公有_____成员相同3)指向基类的对象的指针变量也可以指向___派生类____的对象。
4)若类Y是类X的私有派生类,类Z是类Y的派生类,则类Z__不能___访问类X的保护成员与公有成员。
5)在划线处填上适当的语句,完成下列程序。
#include <math.h>class Point{public:point(double a,double b,double c){___X=a;Y=b;Z=c;___}double Getx(){return X;}double Gety(){return Y;}double Getz(){return Z;}private:______double X;______protected:_____double Y,Z;_____};class Line :_____public______Point{public:Line(double a ,double b,double c,double d)_____:point(a,b,c)__{_ k=d;_ }void show(){cout<<Getx()<<endl;cout<<Gety()<<““<<.<<<endl;cout<<Getz()<<““<<Z<<endl;cout<<K<<endl;}private:double k;};void main(){Line obj(1.2,3.4,5.6,7.8);obj.show();}6)设置虚基类的目的是__解决二义性问题___,可通过___关键字virtual__标识虚基类。
C++语言程序设计实验答案_继承与派生实验07 继承与派生(4学时)(第7章继承与派生)一、实验目的二、实验任务7_1 声明一个基类Animal。
有私有整型成员变量age,构造其派生类dog,在其成员函数SetAge(int n)中直接给age赋值,看看会有什么问题,把age改为公有成员变量,还会有问题吗?编程试试看。
7_2 声明一个基类BaseClass。
有整型成员变量Number,构造其派生类DerivedClass,观察构造函数和析构函数的执行情况。
7_3 声明一个车(vehicle)基类。
具有MaxSpeed、Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类、汽车(motorcar)类。
自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。
从bicycle和motorcar派生出摩托车(motorcycle)类,在继承过程中,注意把vehicle设置为虚基类。
如果不把vehicle设置为虚基类,会有什么问题?编程试试看。
7_4 以实验6中的People(人员)类为基类。
派生出student(学生)类,添加属性:班号char classNo[7];派生出teacher(教师)类,添加属性:职务char principalship[11]、部门char department[21]。
从student类中派生出graduate(研究生)类,添加属性:专业char subject[21]、导师teacher adviser;从graduate类和teacher类派生出TA(助教生)类,注意虚基类的使用。
重载相应的成员函数,测试这些类。
类之间的关系如图7-1所示。
图7-1 类图三、实验步骤1.(编程)声明基类Animal,成员变量age声明为私有的。
构造派生类dog,在其成员函数SetAge(int n)中直接对age赋值时,会出现类似以下的错误提示:(注:在桌面创建一个文本文件,将输出框的内容复制到文本文件中,再复制到Word文件中,不会出现汉字的乱码)把age改为公有变量后重新编译就可以了。
实验5 继承与派生参考答案2 ) 分析下面的程序,指出程序运行的结果:#include<iostream.h>class CBase1{int x ;public:CBase1( ){x=0 ; cout<<"调用构造函数CBase1( )!\n";}CBase1( int a){x=1;cout<<"调用构造函数CBase1( int )!\n";}~CBase1( ){cout<<"调用析构函数~CBase1( )!\n";}};class CBase2{int y;public:CBase2( ){y=0 ;cout<<"调用构造函数CBase2( )!\n";}CBase2(int a){y=a ;cout<<"调用构造函数CBase2(int )!\n";}~CBase2(){cout<<"调用析造函数~CBase2( )!\n";}};class A{ int x;public:A() {x=0 ; cout<<"调用构造函数A( )!\n";}A(int a){x=a;cout<<"调用构造函数A(int )!\n";}~A(){cout<<"调用析构函数~A()!\n";}};class CDerived:public CBase1, virtual public CBase2{A a;public:CDerived(){cout<<"调用构造函数CDerived( )!\n";}CDerived(int x,int y ,int z):a(x),CBase1(y),CBase2(z){cout<<"调用构造函数CDerived(int,int )!\n";}~CDerived(){cout<<"调用析造函数~CDerived( )!\n";}};void main(){CDerived*x=new CDerived; CDerived y(2,3,4);delete x;cout<<"main()函数结束!\n"; }程序分析:a)类分析:本程序有三个类,其中类CDerived公有继承类CBase1和虚基类CBase2,类CDerived使用类A。
实验七继承和派生实验目的∙学习声明和使用类的继承关系,声明派生类。
∙熟悉不同继承方式下对基类成员的访问控制。
∙学习利用虚基类解决二义性问题。
∙理解继承中构造函数和析构函数的调用规则。
实验内容:一、程序分析题1阅读下面的程序,写出运行结果。
#include<iostream>using namespace std;class A{public:A(){a=0;cout<<"调用A的默认构造函数!\n";}A(int i){a=i;cout<<"调用A的带参数构造函数!\n";}~A(){cout<<"调用A的默认析构函数!\n";}void Print() const{cout<<a<<",";}int Geta(){return a;}private:int a;};class B:public A{public:B(){b=0;cout<<"调用B的默认构造函数!\n";}B(int i,int j,int k);~B(){cout<<"调用B的默认析构函数!\n";}void Print();private:int b;A aa;};B::B(int i,int j,int k):A(i),aa(j){b=k;cout<<"调用B的构造函数!\n";};void B::Print(){A::Print();cout<<b<<","<<aa.Geta()<<endl;int main(){B bb(1,2,5);bb.Print();return 0;}2阅读下面程序,写出运行结果。
继承与派生类知识要点1.掌握继承和派生的定义,派生类的定义方法。
(1)掌握继承的两种类型:单继承和多继承。
(2)掌握private,public,protected三种继承方式的特点。
继承方式决定了基类中的成员在派生类中的属性。
三种继承方式的共同点:基类的private成员在派生类中不可见。
区别:对于私有继承,基类的public、protected成员在派生类中作为private成员;对于公有继承,基类的public、protected成员在派生类中访问属性不变;对于保护继承,基类的public、protected成员在派生类中作为protected成员。
(3)掌握派生类中的构造函数和析构函数的使用。
基类的构造函数和析构函数不能继承,所以必要时在派生类中定义自己的构造函数和析构函数。
派生列的构造函数完成基类中新增数据成员和基类数据成员的初始化,基类数据成员的初始化通过基类构造函数来实现。
(4)掌握派生类的同名覆盖规则。
(5)掌握赋值兼容规则。
基类对象可以使用公有派生类对象来代替,包括:派生类对象可以赋值给基类对象;派生类对象可以初始化基类对象的引用;基类类型指针可以指向派生类对象。
2.掌握多重继承的概念、定义方法、多重继承派生类构造函数的执行顺序。
派生类构造函数的执行顺序是先执行所有基类的构造函数(顺序按照定义派生类时指定的各基类顺序),在执行对象成员所在类的构造函数(顺序按照他们在类中的声明顺序),最后执行派生类构造函数体中的内容。
3.掌握虚基类的概念和定义方法。
在多重继承中,如果多条继承路径上有一个公共的基类,则在这些路径的汇合点上的派生类会产生来自不同路径的公共基类的多个拷贝,如果用virtual把公共基类定义成虚基类,则只会保留公共基类的一个拷贝。
典型例题分析与解答例题1:下列对派生类的描述中,()是错误的。
A.一个派生类可以作为另一个派生类的基类B.派生类至少有一个基类C.派生类的成员除了它自己的成员外,还包含了它的基类成员D.派生类中继承的基类成员的访问权限到派生类保持不变答案:D分析:一个派生类可以作为另一个派生类的基类。
实验4 继承与派生一、实验目的和要求(1)掌握派生类的定义方法和派生类构造函数的定义方法。
(2)掌握不同继承方式的情况下,基类成员在派生类中的访问权限。
(3)掌握在多继承方式的情况下,构造函数与析构函数的调用时机与顺序。
二、实验内容和原理(1)实验指导书P86 1~2任选一题。
(2)实验指导书P89 3~4任选一题。
三、实验环境联想计算机,Windows XP操作系统,Visual C++ 6.0四、算法描述及实验步骤(1)输入源程序。
(2)检查程序有无错误(包括语法错误和逻辑错误),有则改之。
(3)编译和连接,仔细分析编译信息,如有错误应找出原因并改正之。
(4)运行程序,分析结果,在原有程序得出正确结果后,修改程序,将其改写为在类模板外定义,再按第(3)步骤运行。
(5)将调试好的程序保存在自己的用户目录中,文件名自定。
五、调试过程(1)2(2)4六、实验结果(1)2(2)4七、总结(1)掌握构造函数和析构函数的定义方法(2)构造函数调用顺序:先调用所有基类的构造函数,然后调用派生类的构造函数;(3)析构函数调用顺序:先调用派生类的析构函数,然后调用基类的析构函数,其顺序正好与构造函数调用顺序相反。
八、附录:(1)代码如下#include<iostream>using namespace std;class Base1{public:Base1(){cout<<"constructing Base1"<<endl;}~Base1(){cout<<"destructing Base1"<<endl;}};class Base2{public:Base2(){cout<<"constructing Base2"<<endl;}~Base2(){cout<<"destructing Base2"<<endl;}};class Derived1:public Base1,virtual public Base2{public:Derived1(){cout<<"constructing Derived1"<<endl;}~Derived1(){cout<<"destructing Derived1"<<endl;}};class Derived2:public Base1,virtual public Base2{public:Derived2(){cout<<"constructing Derived2"<<endl;}~Derived2(){cout<<"destructing Derived2"<<endl;}};class Derived3:public Derived1,virtual public Derived2 {public:Derived3(){cout<<"constructing Derived3"<<endl;}~Derived3(){cout<<"destructing Derived3"<<endl;}};int main(){Derived3 obj;return 0;}(2)4代码如下#include<iostream>using namespace std;const double PI=3.14;class Shape{public:double area()const{return 0.0;}void display(){};};class TwoDimShape:virtual public Shape{};class ThreeDimShape:virtual public Shape{};class Circle:public TwoDimShape{public:Circle(double myr){R=myr;}double area()const{return PI*R*R;}void display(){cout<<"Area of circle is ";}private:double R;};class Rectangle:public TwoDimShape{public:Rectangle(double myl,double myw){L=myl;W=myw;}double area()const{return L*W;}void display(){cout<<"Area of rectangle is";}。
继承和派生练习一1.以日期类cDate(有数据成员年月日)为基类派生日期时间类cTime,新增数据成员时分秒,要求有构造函数、输出所有成员的函数,测试程序正确性。
#include<iostream.h>class cDay{int ye,mo,da;public:cDay(int a=2000,int b=1,int c=1){ye=a,mo=b,da=c;}void Dout(void){cout<<ye<<' '<<mo<<' '<<da<<endl;}};class cTime:public cDay{int ho,mi,se;public:cTime(int a=2000,int b=1,int c=1,int d=12,int e=12,int f=12):cDay(a,b,c){ho=d,mi=e,se=f;}void Tout(void){Dout();cout<<ho<<' '<<mi<<' '<<se<<endl;}};void main(void){cTime t1(2010,4,30,15,20,23);t1.Tout();}2.以三维坐标类cPoint为基类派生圆类cCircle,新增数据成员半径;再以圆类为基类派生圆柱体类cColumn,新增数据成员高度,要求有构造函数、输出所有成员的函数,在相关类中定义求圆面积的成员函数、求体积的成员函数,测试程序正确性。
#include<iostream.h>#define PI 3.1415926class cPoint{float x,y,z;public:cPoint(float a=1,float b=1,float c=1){x=a,y=b,z=c;}void Pout(void){cout<<"x="<<x<<" y="<<y<<" z="<<z;}};class cCircle:public cPoint{float r;public:cCircle(float a=1,float b=1,float c=1,float d=2):cPoint(a,b,c){r=d;}float area(void){return PI*r*r;}void Cout(void){Pout();cout<<" r="<<r;}};class cColumn:public cCircle{float h;public:cColumn(float a=1,float b=1,float c=1,float d=2,float e=3):cCircle(a,b,c,d){ h=e;}float v(void){return area()*h;}void Coout(void){Cout();cout<<" h="<<h<<endl;}};void main(void){cCircle t1(1,2,3,4);t1.Cout();cout<<" area="<<t1.area()<<endl;cColumn t2(2,3,4,5,6);t2.Coout();cout<<"v="<<t2.v()<<endl;}。
实验07 继承与派生(4学时)(第7章继承与派生)一、实验目的二、实验任务7_1 声明一个基类Animal。
有私有整型成员变量age,构造其派生类dog,在其成员函数SetAge(int n)中直接给age 赋值,看看会有什么问题,把age改为公有成员变量,还会有问题吗?编程试试看。
7_2 声明一个基类BaseClass。
有整型成员变量Number,构造其派生类DerivedClass,观察构造函数和析构函数的执行情况。
7_3 声明一个车(vehicle)基类。
具有MaxSpeed、Weight等成员变量,Run、Stop等成员函数,由此派生出自行车(bicycle)类、汽车(motorcar)类。
自行车(bicycle)类有高度(Height)等属性,汽车(motorcar)类有座位数(SeatNum)等属性。
从bicycle和motorcar派生出摩托车(motorcycle)类,在继承过程中,注意把vehicle设置为虚基类。
如果不把vehicle设置为虚基类,会有什么问题?编程试试看。
7_4 以实验6中的People(人员)类为基类。
派生出student(学生)类,添加属性:班号char classNo[7];派生出teacher(教师)类,添加属性:职务char principalship[11]、部门char department[21]。
从student类中派生出graduate(研究生)类,添加属性:专业char subject[21]、导师teacher adviser;从graduate类和teacher类派生出TA(助教生)类,注意虚基类的使用。
重载相应的成员函数,测试这些类。
类之间的关系如图7-1所示。
图7-1 类图三、实验步骤1.(编程)声明基类Animal,成员变量age声明为私有的。
构造派生类dog,在其成员函数SetAge(int n)中直接对age赋值时,会出现类似以下的错误提示:(注:在桌面创建一个文本文件,将输出框的内容复制到文本文件中,再复制到Word文件中,不会出现汉字的乱码)把age改为公有变量后重新编译就可以了。
程序名:lab7_1.cpp。
★程序及运行结果:int age;};class dog:public Animal{public:void SetAge(int n){ age=n; }int GetAge(){ return age; }};void main(){ dog d; d.SetAge(3); cout<<"Age="<<d.GetAge()<<endl; }用private时的结果:1>------ 已启动生成: 项目: cpp, 配置: Debug Win32 ------1>生成启动时间为 2013-2-18 11:10:35。
1>InitializeBuildStatus:1> 正在创建“Debug\cpp.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
1>ClCompile:1> main.cpp1>f:\projects\cpp\cpp\main.cpp(13): error C2248: “Animal::age”: 无法访问 private 成员(在“Animal”类中声明)1> f:\projects\cpp\cpp\main.cpp(8) : 参见“Animal::age”的声明1> f:\projects\cpp\cpp\main.cpp(5) : 参见“Animal”的声明1>f:\projects\cpp\cpp\main.cpp(14): error C2248: “Animal::age”: 无法访问 private 成员(在“Animal”类中声明)1> f:\projects\cpp\cpp\main.cpp(8) : 参见“Animal::age”的声明1> f:\projects\cpp\cpp\main.cpp(5) : 参见“Animal”的声明1>1>生成失败。
1>1>已用时间 00:00:03.28========== 生成: 成功0 个,失败1 个,最新0 个,跳过0 个==========用public时的结果:2.(编程)声明一个基类BaseClass,构造其派生类DerivedClass。
在构造函数和析构函数中用cout输出提示信息,观察构造函数和析构函数的执行情况。
程序名:lab7_2.cpp。
参考的运行结果:★程序及运行结果://lab7_2.cpp#include<iostream>using namespace std;class BaseClass{public:BaseClass(){ cout<<"构造了一个BaseClass类的对象."<<endl; }~BaseClass(){ cout<<"析构了一个BaseClass类的对象."<<endl; } private:int Number;};class DeriveClass:public BaseClass{public:DeriveClass(){ cout<<"构造了一个DeriveClass类的对象."<<endl; } ~DeriveClass(){ cout<<"析构了一个DeriveClass类的对象."<<endl; } };void main(){ DeriveClass a; }3.(操作)用调试功能跟踪程序lab7_2的执行过程。
观察基类和派生类的构造函数和析构函数的执行情况。
4.(编程)声明一个车(vehicle)虚基类。
由此派生出自行车(bicycle)类、汽车(motorcar)类,注意把vehicle派生为虚基类。
再从bicycle和motorcar派生出摩托车(motorcycle)类,在main()函数中测试这个类。
程序名:lab7_3.cpp。
参考的运行结果:★程序及运行结果://lab7_3.cpp#include<iostream>using namespace std;class vehicle{//车类,作为基类protected:int MaxSpeed,Weight;//最大速度,重量public:void Run(){ cout<<"车vehicle类开始运行!"<<endl; }void Stop(){ cout<<"车vehicle类停止运行!"<<endl; }};class bicycle:virtual public vehicle{//自行车类:公有继承虚基类vehicleprotected:int Height;//高度};class motorcar:virtual public vehicle{//汽车类:公有继承虚基类vehicle为什么?按推算应该是:vehicle占用8字节;bicycle占用12字节;motorcar占用12字节;motorcycle占用16字节。
5.(验证)把vehicle设置为非虚基类。
再编译一次,此时系统报错,无法编译成功。
这是因为若不把vehicle设置为虚基类,会出现二义性错误,程序不能成功编译。
访问vehicle的成员时指明继承路径后,可以纠正二义性错误,试修改程序,然后运行。
★程序的运行结果:(1) 没有指明继承路径(运行结果)将上面的程序的bicycle类和motorcar类改为非虚基类公有继承vehicle类后,编译时出现二义(ambiguous)性错误:1>------ 已启动生成: 项目: cpp, 配置: Debug Win32 ------1>生成启动时间为 2013-2-18 11:23:32。
1>InitializeBuildStatus:1> 正在创建“Debug\cpp.unsuccessfulbuild”,因为已指定“AlwaysCreate”。
1>ClCompile:1> main.cpp1>f:\projects\cpp\cpp\main.cpp(27): error C2385: 对“MaxSpeed”的访问不明确1> 可能是“MaxSpeed”(位于基“vehicle”中)1> 也可能是“MaxSpeed”(位于基“vehicle”中)(2) 指明继承路径(程序及运行结果)将vehicle中数据成员和函数成员指明路径。
mt.bicycle::Run();//修改,指明路径mt.Setdatabicycle(100,200,130,2);mt.Showbicycle();mt.motorcar::Stop();//修改,指明路径}6. 以实验6中的people(人员)类为基类,派生相应的类。
按任务7_4的要求编写程序,并运行。
参考的运行结果:★程序及运行结果:(1) lab6_7.h:People(人员)类的声明及成员函数的实现//lab6_7.h#include<iostream>#include<cstring>using namespace std;class Date{private:int yy,mm,dd;public:Date(){ }Date(Date &d) : yy(d.yy),mm(d.mm),dd(d.dd){}//增添~Date(){ }int Getyy()const{ return yy; }(2) lab7_4.h:People类的派生类。