继承与派生

实验四 继承与派生 一.实验目的及要求

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)在上一步的基础上,再定义一个第三层类MotorCycle,该类以公有继承方式继承了第二层的Bicycle和Car类。定义其构造函数,要调用两个直接基类的构造函数,再改造函数Show(),输出所有四个成员变量的信息。主函数中只定义类MotorCycle的对象并调用相应的函数,代码请参考实验指导的(4)。程序进行编译,会产生4个错误、8个警告,因为存在二义性问题,请采用在同名成员前增加“基类名::”以消除二义性直到程序正确,观察运行结果。

(5)再将代码恢复至上一步未修改前,即存在4个错误、8个警告的状态,再作一定的修改,将Vehicle声明为虚基类以消除二义性,同时修改第三层的构造函数,其余代码不变,具体请参考实验指导的(5),观察运行结果,理解此时构造函数、析构函数的调用顺序及用虚基类消除二义性的原理。 三.试验程序及结果 1.

#include using namespace std;

{

public: A(){ cout

class B: public A {

public: B(){ cout

class C: public B {

public: C(){ cout

int main(void) { C obj; system("PAUSE"); return 0; }

2.

#include using namespace std;

{

protected: int a;

public: A(int x): a(x){ } void Show() const{ cout

class B {

protected: int b;

public: B(int x): b(x){ } void Show() const{ cout

class C: public A, public B {

public: C(int x, int y): A(x), B(y){ } void Show() const { cout

int main(void) { C obj(5, 18); obj.Show(); obj.A::Show(); obj.B::Show(); system("PAUSE"); return 0; }

3.

#include using namespace std;

class A {

private: int a; public:

// 公有函数: A(int x): a(x){ } void Show() const { cout

class B: public A {

protected: int b;

public: B(int x, int y): A(x), b(y){ } void Show() const { A::Show(); cout

int main(void) { B obj(5, 18); obj.Show(); system("PAUSE");

}

4.

#include using namespace std; class Base { private: int m; public: Base(int a): m(a){ } Base(const Base &copy) { m = copy.m; } void Show() const { cout

} Derived obj(10, 18); obj.Show(); system("PAUSE"); return 0;

5.

#include using namespace std; /

class Person {

protected: char name[18]; int age; char sex[3]; public: Person(char nm[], int ag, char sx[]) { strcpy(name, nm); age = ag; strcpy(sex, sx); } void Show() const { cout

class Teacher: virtual public Person {

protected: char title[18]; public: Teacher(char nm[], int ag, char sx[], char tl[]): Person(nm, ag, sx)

{ strcpy(title, tl); } void Show() const { Person::Show(); cout

class Cadre: virtual public Person {

protected: char post[18]; public: Cadre(char nm[], int ag, char sx[], char pt[]): Person(nm, ag, sx { strcpy(post, pt); } void Show() const { Person::Show(); cout

class TeacherCadre: public Teacher, public Cadre {

protected: double wages; public: TeacherCadre(char nm[], int ag, char sx[], char tl[], char pt[], double wg) : Person(nm, ag, sx), Teacher(nm, ag, sx, tl), Cadre(nm, ag, sx, pt) { wages = wg; } void Show() const { Person::Show(); cout

int main(void) {

}

Teacher objTeacher("文冠杰", 48, "男", "教授"); Cadre objCadre("周杰", 56, "男", "院长"); TeacherCadre objTeacherCadre("李靖", 50, "女", "教授", "院长", 6890); objTeacher.Show(); objCadre.Show(); objTeacherCadre.Show();

system("PAUSE"); return 0;

6.

#include using namespace std;

class Staff {

protected: // 数据成员: int num; char name[18]; double rateOfAttend; double basicSal ; double prize ; static int count;

public: Staff(){ } void Input() { num = ++count; cout > name; cout > basicSal; cout > prize; cout > rateOfAttend; } void Output() const { cout

int Staff::count = 1000;

class Saleman : virtual public Staff {

protected: float deductRate; float personAmount;

public: Saleman (){ }; void Input( void ) { Staff::Input(); cout > personAmount;

cout > deductRate; } void Output() const { Staff::Output(); cout

class Manager: virtual public Staff {

protected: double totalDeductRate; double totalAmount;

public: Manager(){ } void Input( void ) { Staff::Input(); cout > totalAmount; cout > totalDeductRate; } void Output() const { Staff::Output(); cout

}

};

class SaleManager: public Saleman, public Manager

{

public:

SaleManager(){ };

void Input( void )

{

Staff::Input();

cout

cin >> personAmount;

cout

cin >> deductRate;

cout

cin >> totalAmount;

cout

cin >> totalDeductRate;

}

void Output() const

{

Staff::Output();

cout

cout

cout

cout

}

void OutputWage() const

{

cout

}

};

int main(void)

{

char flag = 'Y';

while (toupper(flag) == 'Y')

{

int n;

cin >> n;

if (n == 1)

{ // 员工

Staff objStaff;

objStaff.Input();

objStaff.Output();

objStaff.OutputWage();

}

else if (n == 2)

{ // 销售员

Saleman objSaleman;

objSaleman.Input();

objSaleman.Output();

objSaleman.OutputWage();

}

else if (n == 3)

{

Manager objManager;

objManager.Input();

objManager.Output();

objManager.OutputWage();

}

else if (n == 4)

{

SaleManager objSaleManager;

objSaleManager.Input();

objSaleManager.Output();

objSaleManager.OutputWage();

}

else

{ // 其它情况, 表示选择有误

cout

}

cout

cin >> flag;

}

system("PAUSE");

return 0;

}

五.实验总结

通过这次实验,我对类的继承和派生,派生类构造函数初始化基类成员和对象成员的方法,以及赋值兼容原则有了更深的理解

实验四 继承与派生 一.实验目的及要求

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)在上一步的基础上,再定义一个第三层类MotorCycle,该类以公有继承方式继承了第二层的Bicycle和Car类。定义其构造函数,要调用两个直接基类的构造函数,再改造函数Show(),输出所有四个成员变量的信息。主函数中只定义类MotorCycle的对象并调用相应的函数,代码请参考实验指导的(4)。程序进行编译,会产生4个错误、8个警告,因为存在二义性问题,请采用在同名成员前增加“基类名::”以消除二义性直到程序正确,观察运行结果。

(5)再将代码恢复至上一步未修改前,即存在4个错误、8个警告的状态,再作一定的修改,将Vehicle声明为虚基类以消除二义性,同时修改第三层的构造函数,其余代码不变,具体请参考实验指导的(5),观察运行结果,理解此时构造函数、析构函数的调用顺序及用虚基类消除二义性的原理。 三.试验程序及结果 1.

#include using namespace std;

{

public: A(){ cout

class B: public A {

public: B(){ cout

class C: public B {

public: C(){ cout

int main(void) { C obj; system("PAUSE"); return 0; }

2.

#include using namespace std;

{

protected: int a;

public: A(int x): a(x){ } void Show() const{ cout

class B {

protected: int b;

public: B(int x): b(x){ } void Show() const{ cout

class C: public A, public B {

public: C(int x, int y): A(x), B(y){ } void Show() const { cout

int main(void) { C obj(5, 18); obj.Show(); obj.A::Show(); obj.B::Show(); system("PAUSE"); return 0; }

3.

#include using namespace std;

class A {

private: int a; public:

// 公有函数: A(int x): a(x){ } void Show() const { cout

class B: public A {

protected: int b;

public: B(int x, int y): A(x), b(y){ } void Show() const { A::Show(); cout

int main(void) { B obj(5, 18); obj.Show(); system("PAUSE");

}

4.

#include using namespace std; class Base { private: int m; public: Base(int a): m(a){ } Base(const Base &copy) { m = copy.m; } void Show() const { cout

} Derived obj(10, 18); obj.Show(); system("PAUSE"); return 0;

5.

#include using namespace std; /

class Person {

protected: char name[18]; int age; char sex[3]; public: Person(char nm[], int ag, char sx[]) { strcpy(name, nm); age = ag; strcpy(sex, sx); } void Show() const { cout

class Teacher: virtual public Person {

protected: char title[18]; public: Teacher(char nm[], int ag, char sx[], char tl[]): Person(nm, ag, sx)

{ strcpy(title, tl); } void Show() const { Person::Show(); cout

class Cadre: virtual public Person {

protected: char post[18]; public: Cadre(char nm[], int ag, char sx[], char pt[]): Person(nm, ag, sx { strcpy(post, pt); } void Show() const { Person::Show(); cout

class TeacherCadre: public Teacher, public Cadre {

protected: double wages; public: TeacherCadre(char nm[], int ag, char sx[], char tl[], char pt[], double wg) : Person(nm, ag, sx), Teacher(nm, ag, sx, tl), Cadre(nm, ag, sx, pt) { wages = wg; } void Show() const { Person::Show(); cout

int main(void) {

}

Teacher objTeacher("文冠杰", 48, "男", "教授"); Cadre objCadre("周杰", 56, "男", "院长"); TeacherCadre objTeacherCadre("李靖", 50, "女", "教授", "院长", 6890); objTeacher.Show(); objCadre.Show(); objTeacherCadre.Show();

system("PAUSE"); return 0;

6.

#include using namespace std;

class Staff {

protected: // 数据成员: int num; char name[18]; double rateOfAttend; double basicSal ; double prize ; static int count;

public: Staff(){ } void Input() { num = ++count; cout > name; cout > basicSal; cout > prize; cout > rateOfAttend; } void Output() const { cout

int Staff::count = 1000;

class Saleman : virtual public Staff {

protected: float deductRate; float personAmount;

public: Saleman (){ }; void Input( void ) { Staff::Input(); cout > personAmount;

cout > deductRate; } void Output() const { Staff::Output(); cout

class Manager: virtual public Staff {

protected: double totalDeductRate; double totalAmount;

public: Manager(){ } void Input( void ) { Staff::Input(); cout > totalAmount; cout > totalDeductRate; } void Output() const { Staff::Output(); cout

}

};

class SaleManager: public Saleman, public Manager

{

public:

SaleManager(){ };

void Input( void )

{

Staff::Input();

cout

cin >> personAmount;

cout

cin >> deductRate;

cout

cin >> totalAmount;

cout

cin >> totalDeductRate;

}

void Output() const

{

Staff::Output();

cout

cout

cout

cout

}

void OutputWage() const

{

cout

}

};

int main(void)

{

char flag = 'Y';

while (toupper(flag) == 'Y')

{

int n;

cin >> n;

if (n == 1)

{ // 员工

Staff objStaff;

objStaff.Input();

objStaff.Output();

objStaff.OutputWage();

}

else if (n == 2)

{ // 销售员

Saleman objSaleman;

objSaleman.Input();

objSaleman.Output();

objSaleman.OutputWage();

}

else if (n == 3)

{

Manager objManager;

objManager.Input();

objManager.Output();

objManager.OutputWage();

}

else if (n == 4)

{

SaleManager objSaleManager;

objSaleManager.Input();

objSaleManager.Output();

objSaleManager.OutputWage();

}

else

{ // 其它情况, 表示选择有误

cout

}

cout

cin >> flag;

}

system("PAUSE");

return 0;

}

五.实验总结

通过这次实验,我对类的继承和派生,派生类构造函数初始化基类成员和对象成员的方法,以及赋值兼容原则有了更深的理解


相关文章

  • c++--公有继承,私有继承和保护继承
  • 1.   公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的. 2.   私有继承(private) 私有继承的特点是基类的公有成员和保护成员都作为派生类 ...查看


  • C++题目作业14
  • HZAU-专业C++作业14(继承与多态性) 判断题 1. 派生类的构造函数的初始化列表中如果不写对基类构造函数的调用,则自动调用基类的拷贝构造函数.f 2. 在多继承情况下,派生类的构造函数中基类构造函数的执行顺序取决于定义派生类时所指定 ...查看


  • 继承与派生实验报告
  • <面向对象程序设计> 课程设计报告 专 业 班 级 姓 名 学 号 指导教师 起止时间 2011.2~2011.4 课程设计课题之一:继承和派生 一. 任务描述 1.掌握利用单一继承和多重继承方式定义派生类的方法: 2.深刻理解 ...查看


  • 虚,纯虚等的概念
  • 1. 析构函数和虚析构函数 如果基类的析构函数是虚的,那么它的派生类的析构函数都是虚的 这将导致:当派生类析构的时候,它的所有的基类的析构函数都将得到调用 否则,只调用派生类的析构函数(这可能导致基类的某些对象没有得到释放) 所以CObje ...查看


  • C++程序设计实验5-8
  • 实验五 构造函数与析构函数的编程 一.实验目的 1.进一步加深对类和对象的理解. 2.掌握类的构造函数和析构函数的概念.意义和使用方法. 3.掌握重载构造函数的含义和使用. 4.编写一个较为复杂的类和对象的应用程序. 二.实验内容 1.设计 ...查看


  • c++题库 以及答案
  • 一.单选题 1. C++源程序文件的缺省扩展名为( ). A. cpp B. exe C. obj D. lik 2. 由C++源程序文件编译而成的目标文件的缺省扩展名为( ). A. cpp B. exe C. obj D. lik 3. ...查看


  • 2011上海专升本C++考试大纲
  • <C++程序设计>考试大纲 一.基本要求 1. 掌握C++语言的基本语法规则. 2.掌握程序设计的三种基本结构. 3.掌握函数.指针和结构体的基本知识及相关应用. 4.熟练掌握有关类与对象的相关知识. 5.能够采用面向过程和面向 ...查看


  • 面向对象程序设计历史及发展
  • 面向对象程序设计的历史及发展 姓名:郭一恒 班级:0901 学号:[1**********]14 自从计算机发展以来,程序设计的方法为了适应越来越复杂的程序设计的需要而发生了急剧的变化.计算机刚问世时.程序设计是通过计算机的控制板用二进制机 ...查看


  • 考试中经典的c++选择题库
  • C++选择题集 1. 下列的各类函数中,不是类的成员函数.( C ) A) 构造函数 B)析构函数 C)友元函数 D)拷贝初始化构造函数 2. 作用域运算符"::"的功能是:( B ) A) 标识作用域的级别的 B)指出 ...查看


热门内容