C++程序设计基础实验-实验六 继承与派生

实验六 继承与派生

一、实验目的

  • 掌握派生类的定义方法和实现,能正确访问继承层次中的各种类成员。
  • 掌握继承机制中派生类的构造函数和析构函数的执行顺序。

二、实验内容

  1. 请改写教材例题7-1的Rectangle类公有继承Point类。要求:(30分)
    (1)为派生类增加构造函数、析构函数,及其它必要的函数。
    (2)派生类中有能够打印矩形信息的函数,包括的信息有矩形点的位置坐标、矩形长宽值及面积。

  2. 设计一个基类:学生类(Student),采用公有继承的方式派生出一个研究生类(PostGraduate),要求:(20分)
    (1)Student类中包含:学号、姓名、性别、专业。
    (2)要求在PostGraduate类中增加导师(tutor)、津贴(allowance)、研究方向(researchArea)。
    (3)两个类中都包含:display()函数,用于输出本类中的成员信息。
    可以用如下代码测试所建立的类是否正确。

int main(){
    Student s1(“20190001”, “Michael”, “Male”, “Computer Science”);
    //参数分别为:学号,姓名,性别,专业
    s1.display();
    PostGraduate p1(……);//导师:“Liu”,津贴:“1000”,研究方向:“Deep learning”
    p1.display();
        return 0;
}
  1. 定义一个基类BaseClass,它有公有成员函数func1(),func2(),函数内打印出类名及函数名,有私有数据成员int i。从它派生出类DerivedClass,有公有成员函数func1(),函数内打印出类名及函数名,私有数据成员int j,在主函数中分别用BaseClass及Derivedclass类的指针去调用func1(),func2,观察运行结果。要求:(20分)
    (1)注意派生类的构造函数须写正确;
    (2)分析通过指针调用成员函数的运行结果。

  2. 定义一个Document类,有数据成员name,从Document派生出Book类,增加数据成员pageCount。观察基类与派生类的构造函数和析构函数的调用顺序。(20分)

  3. 组合与继承有什么共同点和差异?通过组合生成的类与被组合的类之间的逻辑关系是什么?继承呢?请分析总结。(5分)

三、实验步骤及结果

  1. 请改写教材例题7-1的Rectangle类公有继承Point类。要求:(30分)
    (1)为派生类增加构造函数、析构函数,及其它必要的函数。
    (2)派生类中有能够打印矩形信息的函数,包括的信息有矩形点的位置坐标、矩形长宽值及面积。
#include<iostream>
using namespace std;
class Point{
	public:
		Point(float x, float y){
			this->x=x;	this->y=y;
		}
		void move(float offX,float offY){
			x+=offX;	y+=offY;
		}
		float getX() const{return x;}
		float getY() const{return y;}
	private:
		float x,y;
};
class Rectangle:public Point{
	public:
		Rectangle(float x,float y,float w,float h):Point(x,y){
			this->w=w;	this->h=h;
		}
		float getH() const{return h;}
		float getW() const{return w;}
		~Rectangle(){
			cout<<"调用了Rectangle的析构函数。"<<endl;
		}
		void zuobiao(){
			cout<<"坐标为:("<<this->getX()<<","<<this->getY()<<")"<<"\t";
			cout<<"("<<this->getX()+w<<","<<this->getY()<<")"<<"\t";
			cout<<"("<<this->getX()<<","<<this->getY()+h<<")"<<"\t";
			cout<<"("<<this->getX()+w<<","<<this->getY()+h<<")"<<endl;
		}
		double area(){
			return this->h*this->w;
		}
	private:
		float h,w;
};
int main(){
	Rectangle r(2,3,4.1,5.7);
	r.zuobiao();
	cout<<"其面积为:"<<r.area()<<endl;
	return 0;
}

运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d8TO4k6t-1667656379440)(https://dn-simplecloud.shiyanlou.com/courses/uid1760929-20211205-1638717424224)]

  1. 设计一个基类:学生类(Student),采用公有继承的方式派生出一个研究生类(PostGraduate),要求:(20分)
    (1)Student类中包含:学号、姓名、性别、专业。
    (2)要求在PostGraduate类中增加导师(tutor)、津贴(allowance)、研究方向(researchArea)。
    (3)两个类中都包含:display()函数,用于输出本类中的成员信息。

可以用如下代码测试所建立的类是否正确。

int main(){
    Student s1(“20190001”, “Michael”, “Male”, “Computer Science”);
    //参数分别为:学号,姓名,性别,专业
    s1.display();
    PostGraduate p1(……);//导师:“Liu”,津贴:“1000”,研究方向:“Deep learning”
    p1.display();
        return 0;
}

代码:

#include<iostream>
using namespace std;
#include<string>
class Student{
	private:
		int score;	string name;	string sex;		string major;
	public:
		Student(int score0,string name0,string sex0,string major0):score(score0),name(name0),sex(sex0),major(major0){}
		void display(){
			cout<<"学号为:"<<score<<"\t";
			cout<<"姓名为:"<<name<<"\t";
			cout<<"性别为:"<<sex<<"\t";
			cout<<"专业为:"<<major<<endl;
		}
};
class PostGraduate: public Student{
	public:
		PostGraduate(int score0,string name0,string sex0,string major0,string tutor0,double allowance0,string researchArea0):Student(score0,sex0,sex0,major0){
		tutor = tutor0;
		allowance = allowance0;
		researchArea = researchArea0;
		}
		void display(){
			cout<<"导师为:"<<tutor<<'\t';
			cout<<"津贴为:"<<allowance<<'\t';
			cout<<"研究方向为:"<<researchArea<<'\t'<<endl;
		}
	private:
		string tutor;	double allowance; 	string researchArea;
};
int main(){
    Student s1(20190001, "Michael", "Male", "Computer Science");
    s1.display();
    cout<<endl;
    PostGraduate p1(20190001, "Michael", "Male", "Computer Science","Liu",1000,"deep learning");
    p1.display();
    return 0;
}

运行结果:
在这里插入图片描述

  1. 定义一个基类BaseClass,它有公有成员函数func1(),func2(),函数内打印出类名及函数名,有私有数据成员int i。从它派生出类DerivedClass,有公有成员函数func1(),函数内打印出类名及函数名,私有数据成员int j,在主函数中分别用BaseClass及Derivedclass类的指针去调用func1(),func2,观察运行结果。要求:(20分)
    (1)注意派生类的构造函数须写正确;
    (2)分析通过指针调用成员函数的运行结果。
#include<iostream>
using namespace std;
class BaseClass{
	private:
		int i;
	public:
		BaseClass(int i0=0):i(i0){}
		void func1(){
			cout<<"类名为:BaseClass"<<endl;
			cout<<"函数名为:func1()"<<endl;
		}
		void func2(){
		cout<<"类名为:BaseClass"<<endl;
		cout<<"函数名为:func2()"<<endl;
		}
};
class Derivedclass:public BaseClass{
	public:
		Derivedclass(int i0=0,int j0=0):BaseClass(i0),j(j0){}
		void func1(){
		cout<<"类名为:Derivedclass"<<endl;
		cout<<"函数名为:func1()"<<endl;
		}
	private:
		int j;
};
int main(){
	BaseClass b(2);
	BaseClass* B = &b;
	B->func1();
	B->func2();
	Derivedclass d;
	Derivedclass *D = &d;
	D->func1();
	D->BaseClass::func1();
	return 0;
}

运行结果:
在这里插入图片描述

  1. 定义一个Document类,有数据成员name,从Document派生出Book类,增加数据成员pageCount。观察基类与派生类的构造函数和析构函数的调用顺序。(20分)
#include<iostream>
using namespace std;
#include<string>
class Document{
	private:
		string name;
	public:
		Document(){cout<<"调用了Document的构造函数。"<<endl;}
		~Document(){cout<<"调用了Document的析构函数。"<<endl;}
};
class Book:public Document{
	private:
		int pageCount;
	public:
		Book(){cout<<"调用了Book的构造函数。"<<endl;}
		~Book(){cout<<"调用了Book的析构函数。"<<endl;}
};
void text01(){
	Book b1;
}
int main(){
	text01();
	return 0;
}

运行结果:
在这里插入图片描述

  1. 组合与继承有什么共同点和差异?通过组合生成的类与被组合的类之间的逻辑关系是什么?继承呢?请分析总结。(5分)
  • 共同点:
    继承和组合的使用都可以减少重复代码,同时若类B是类A的内嵌对象,则B类具有A类的全部数据。
  • 不同点:
    组合是通过在其他类中定义对象来使用类中的方法和属性,不能访问父类的任何接口。 而继承则是从父类中得到方法和属性,即可以得到父类的全部接口,并加以调用。
  • 通过组合生成的类和被组合的类之间的逻辑关系:
    组合生成的类具有被组合类的全部内容,但是并不包括被组合类的全部接口,就是通过被组合的类的对象只能访问组合类的成员函数,但不能直接访问到被组合类的成员函数。
  • 继承类与基类的逻辑关系:
    即通过派生类的对象不但可以访问派生类的成员函数,也能访问基类的成员函数,派生类是可以完全继承基类的任何内容的包括全部接口。

四、实验小结(5分)

问题与解决办法:

  1. 编译出错 :[Error] ‘sqrt’ was not declared in this scope

    解决办法:运用sqrt函数需要头文件#include <math.h>。

  2. 编译出错,提示“[Error] expected before return”

    解决办法:语句结束时的英文下的分号“;”输成了中文下的分号。改正后,错误消失。

  3. 编译出错,提示“ [Error] expected ‘;’ before ‘)’ token”

    解决办法:for循环里的分号“;”写成了逗号“,”。改正后,错误消失。

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子书棋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值