C++程序设计-第11周 继承与派生

简介: 课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565(第10周学校放春假,空一周)【目的】1. 掌握类的派生与继承的概念;2. 学会定义子类,重点是类的构造函数与析构函数第一部分 阅读程序【程序1】阅读下面的程序,写出程序运行结果,上机时再运行,对比结果是否有差异,仔细领会继承,以及基类、派生类中构造函数的写法及执行过

课程首页地址:http://blog.csdn.net/sxhelijian/article/details/7910565

(第10周学校放春假,空一周)

【目的】1. 掌握类的派生与继承的概念;2. 学会定义子类,重点是类的构造函数与析构函数

第一部分 阅读程序
【程序1】阅读下面的程序,写出程序运行结果,上机时再运行,对比结果是否有差异,仔细领会继承,以及基类、派生类中构造函数的写法及执行过程

#include <iostream>
#include <string>
using namespace std;
class Student//声明基类
{
public:                                  //公用部分
    Student(int n, string nam )             //基类构造函数,与例.5相同
    {
        num=n;
        name=nam;
    }
    void display( )                           //成员函数,输出基类数据成员
    {
        cout<<"num:"<<num<<endl<<"name:"<<name<<endl;
    }
protected:                                //保护部分
    int num;
    string name;
};


class Student1: public Student              //声明公用派生类Student1
{
public:
    Student1(int n, string nam,int n1, string nam1,int a, string ad): 					Student(n,nam),monitor(n1,nam1) //派生类构造函数
    {
        age=a;
        addr=ad;
    }
    void show( )
    {
        cout<<"This student is:"<<endl;
        display();                               //输出num和name
        cout<<"age: "<<age<<endl;                //输出age
        cout<<"address: "<<addr<<endl<<endl;     //输出addr
    }


    void show_monitor( )                        //成员函数,输出子对象
    {
        cout<<endl<<"Class monitor is:"<<endl;
        monitor.display( );                       //调用基类成员函数
    }
private:                                      //派生类的私有数据
    Student monitor;                          //定义子对象(班长)
    int age;
    string addr;
};


int main( )
{
    Student1 stud1(10010,"Wang-li",10001,"Li-sun",19,"115 Beijing Road,Shanghai");
    stud1.show( );                       //输出学生的数据
    stud1.show_monitor();                //输出子对象的数据
    return 0;
}

【程序2】先分析程序的执行结果,在上机时运行程序进行对照,再通过单步执行跟踪程序的运行,达到理解基类、派生类中构造函数、析构函数执行过程的目的。
#include <iostream>
using namespace std;
class Part  //部件类
{
    public:
	Part();
	Part(int i);
	~Part();
 private:
	int val;
};
class Whole: public Part
{
    public:
	Whole();
	Whole(int,int,int,int);
	~Whole();
 private:
	Part one;
	Part two;
	int data;
};
Part::Part()
{
    val=0;
	cout<<"The default constructor of part was called "<<val<<endl;
}
Part::Part(int i)
{
    val=i;
	cout<<"The constructor of part was called "<<val<<endl;
}
Part::~Part()
{
	cout<<"The destructor of part was called "<<val<<endl;
}
Whole::Whole()
{
    data=0;
	cout<<"The default constructor of whole was called "<<data<<endl;
}
Whole::Whole(int p, int i,int j,int k):Part(p), two(i),one(j),data(k)
{
    cout<<"The constructor of whole was called "<<data<<endl;
}
Whole::~Whole()
{
	cout<<"The destructor of whole was called "<<data<<endl;
}


int main()
{
    Whole w1;
	Whole w2(1,2,3,4);
	return 0;
}
/* 如果用vs2008,将上面的main()函数删除,换作下面的两个函数
void f()
{
    Whole w1;
	Whole w2(1,2,3,4);
}
int main()
{
    f();
	system("pause");
	return 0;
}
*/

第二部分 实践项目
【项目1】定义点类,并以点类为基类,派生出直线类,从基类中继承的点的信息表示直线的中点。请阅读下面的代码,并将缺少的部分写出来。
#include<iostream>
#include<Cmath>
using namespace std;
class Point //定义坐标点类
{
public:
    Point():x(0),y(0) {};
    Point(double x0, double y0):x(x0), y(y0) {};
    void PrintPoint(); //输出点的信息
    double x,y;   //数据成员,表示点的横坐标和纵坐标
};
void Point::PrintPoint()
{
    cout<<"Point:("<<x<<","<<y<<")";    //输出点
}


class Line: public Point   //利用坐标点类定义直线类, 其基类的数据成员表示直线的中点
{
public:
    Line(Point pt1, Point pt2);  //构造函数,初始化直线的两个端点及由基类数据成员描述的中点,中点的坐标可以由端点坐标计算而来
    double Length();    //计算并返回直线的长度
    void PrintLine();   //输出直线的两个端点和直线长度
private:
    Point pts,pte;   //直线的两个端点
}; 
//下面定义Line类的成员函数
  
int main()
{
    Point ps(-2,5),pe(7,9);
    Line l(ps,pe);
    _____________________;//输出直线l的信息(请补全代码)
    cout<<"\n The middle point of Line: ";
    _____________________ ;//输出直线l中点的信息(请补全代码,调用成员函数完成)
    return 0;
}

【项目2】要求与项目1几乎完全相同(除Point类中的数据成员要求为private型),要求补全点类和直线类的定义,调用main()函数输出一条直线的信息。
    请不要直接copy项目1的代码,通过修改项目1的程序完成项目2的要求。在有关“抄之有道”的学习方法中,我们有阅读代码,然后自己再写出来的建议。所以,项目2可以在以下代码的提示下开始去做,在项目1中获得的经验会有所帮助,这个过程也会对项目1中的收获有更多理解。其实,当这一些技术熟练之后,根据需求会自己设计并实现,那是我们的最终目标。
    项目2可以参考的代码如下,在完成时可以根据需要自行添加其他成员函数,成员函数在类内实现还是类外实现,也可以自行决定。
class Point //定义坐标点类
{
public:
    //定义必要的构造函数
    void PrintPoint(); //输出点的信息
private:
    double x,y;   //点的横坐标和纵坐标
};
class Line: public Point   //利用坐标点类定义直线类, 其基类的数据成员表示直线的中点
{
public:
    Line(Point pts, Point pte);  //构造函数,用初始化直线的两个端点及由基类数据成员描述的中点
    void PrintLine();   //输出直线的两个端点和直线长度
private:
    class Point pts, pte;   //直线的两个端点
};
int main()
{
    Point ps(-2,5),pe(7,9);
    Line l(ps,pe);
    //下面输出直线l的端点、长度和、中点的信息


    return 0;
}

【项目3】定义一个名为CPerson的类,有以下私有成员:姓名、身份证号、性别和年龄,成员函数:构造函数、析构函数、输出信息的函数。并在此基础上派生出CEmployee类,派生类CEmployee增加了两个新的数据成员,分别用于表示部门和薪水。要求派生类CEmployee的构造函数显示调用基类CPerson的构造函数,并为派生类CEmployee定义析构函数,定义输出信息的函数。
class CPerson 
{
protected:
	char *m_szName;
	char *m_szId;
	int m_nSex;//0:women,1:man
	int m_nAge;
public:
	CPerson(char *name,char *id,int sex,int age);
	void Show1();
	~CPerson();  //需要释放建立对象时动态分配的内存
};


class CEmployee:public CPerson
{
private:
	char *m_szDepartment;
	float m_Salary;
public:
	CEmployee(char *name,char *id,int sex,int age,char *department,float salary);
	void Show2();
	~CEmployee();
};


int main()
{
	char name[10],id[19],department[10];
	int sex,age;
	float salary;
	cout<<"input employee's name,id,sex(0:women,1:man),age,department,salary:\n";
	cin>>name>>id>>sex>>age>>department>>salary;
	CEmployee employee1(name,id,sex,age,department,salary);
	employee1.Show2();
	return 0;
}

下面的运行结果供参考:


【项目4】按以下的提示,由基类的设计和测试开始,逐渐地完成各个类的设计,并且完成要求的计算任务:
    (1)先建立一个Point(点)类,包含数据成员x,y(坐标点);
    (2)以Point为基类,派生出一个Circle(圆)类,增加数据成员 (半径);
    (3)再以Circle类为直接基类,派生出一个Cylinder(圆柱体)类,再增加数据成员h(高)。
     要求编写程序,设计出各类中基本的成员函数(包括构造函数、析构函数、修改数据成员和获取数据成员的公共接口、用于输出的重载运算符“<<”函数等),使之能用于处理以上类对象,最后求出圆格柱体的表面积、体积并输出。
   (提示:此任务可以分为三个子任务分成若干步骤进行。先声明基类,再声明派生类,逐级进行,分步调试。——这种方法适用于做任何的项目)




目录
相关文章
|
5天前
|
安全 前端开发 Java
【C++】从零开始认识继承二)
在我们日常的编程中,继承的应用场景有很多。它可以帮助我们节省大量的时间和精力,避免重复造轮子的尴尬。同时,它也让我们的代码更加模块化,易于维护和扩展。可以说,继承技术是C++的灵魂。
11 1
|
5天前
|
安全 程序员 编译器
【C++】从零开始认识继承(一)
在我们日常的编程中,继承的应用场景有很多。它可以帮助我们节省大量的时间和精力,避免重复造轮子的尴尬。同时,它也让我们的代码更加模块化,易于维护和扩展。可以说,继承技术是C++的灵魂。
20 3
【C++】从零开始认识继承(一)
|
4天前
|
存储 编译器 C++
C++中的继承
C++中的继承
11 0
|
7天前
|
设计模式 算法 编译器
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
【C++入门到精通】特殊类的设计 |只能在堆 ( 栈 ) 上创建对象的类 |禁止拷贝和继承的类 [ C++入门 ]
11 0
|
8天前
|
安全 程序员 编译器
【C++】继承(定义、菱形继承、虚拟继承)
【C++】继承(定义、菱形继承、虚拟继承)
15 1
|
安全 编译器 程序员
[C++基础]-继承
[C++基础]-继承
|
14天前
|
C++ 芯片
【期末不挂科-C++考前速过系列P4】大二C++实验作业-继承和派生(3道代码题)【解析,注释】
【期末不挂科-C++考前速过系列P4】大二C++实验作业-继承和派生(3道代码题)【解析,注释】
|
16天前
|
安全 Java 程序员
【C++笔记】从零开始认识继承
在编程中,继承是C++的核心特性,它允许类复用和扩展已有功能。继承自一个基类的派生类可以拥有基类的属性和方法,同时添加自己的特性。继承的起源是为了解决代码重复,提高模块化和可维护性。继承关系中的类形成层次结构,基类定义共性,派生类则根据需求添加特有功能。在继承时,需要注意成员函数的隐藏、作用域以及默认成员函数(的处理。此外,继承不支持友元关系的继承,静态成员在整个继承体系中是唯一的。虽然多继承和菱形继承可以提供复杂的设计,但它们可能导致二义性、数据冗余和性能问题,因此在实际编程中应谨慎使用。
17 1
【C++笔记】从零开始认识继承
|
19天前
|
设计模式 编译器 数据安全/隐私保护
C++ 多级继承与多重继承:代码组织与灵活性的平衡
C++的多级和多重继承允许类从多个基类继承,促进代码重用和组织。优点包括代码效率和灵活性,但复杂性、菱形继承问题(导致命名冲突和歧义)以及对基类修改的脆弱性是潜在缺点。建议使用接口继承或组合来避免菱形继承。访问控制规则遵循公有、私有和受保护继承的原则。在使用这些继承形式时,需谨慎权衡优缺点。
24 1
|
21天前
|
编译器 C++
【C++进阶(八)】C++继承深度剖析
【C++进阶(八)】C++继承深度剖析