C++ 多态之继承2-继承的相关基础

来源:互联网 发布:java code style 编辑:程序博客网 时间:2024/05/01 19:07
之前我们讲了一下关于继承的一些抽象概念,现在我们来聊聊如何在c++中使用继承。

在c++中,继承发生在两个类之间。当一个类从另外一个继承,这个派生类将会继承基类的变量(variables)以及函数(functions)。这些变量以及函数变成了派生类的一部分。

A Person base class

如下是一个简单的基类(人):

#include <string>class Person{public:    std::string m_strName;    int m_nAge;    bool m_bIsMale;     std::string GetName() { return m_strName; }    int GetAge() { return m_nAge; }    bool IsMale() { return m_bIsMale; }     Person(std::string strName = "", int nAge = 0, bool bIsMale = false)        : m_strName(strName), m_nAge(nAge), m_bIsMale(bIsMale)    {    }};
这个基类包含了一些人的一些信息,如名字(name),年龄(age),性别(sex).需要注意的两点是.首先,我们仅仅是定义了所有人都共有的的属性,它能被所有人复用。其次,我们将所有的变量和函数设置为公有(public),仅仅是为了简化这个例子,通常情况下,应该讲变量设置为私有(private)。

 A BaseballPlayer derived class

class BaseballPlayer{public:    double m_dBattingAverage;    int m_nHomeRuns;};
注意到它并没有包含棒球运动员的姓名,年龄以及性别。我们可以添加一些变量来直接保存这些信息,但是我们已经定义了一个通用的Person类,所有我们只需要简单的复用它。

逻辑上,我们知道棒球运动员和人有一些关系。需要弄清楚的是:a baseball player “has a” person, 还是 “is-a” person?显而易见,a baseball player "is-a" person,所有baseball player 类使用继承而不是组合。
要继承Person类,语法上很简单。在声明完BaseballPlayer类后,加上关键字“public”,然后是我们希望继承的类。这称为共有继承,在后面我们会讲更多关于共有继承。

// BaseballPlayer publicly inheriting Personclass BaseballPlayer : public Person{public:    double m_dBattingAverage;    int m_nHomeRuns;     BaseballPlayer(double dBattingAverage = 0.0, int nHomeRuns = 0)       : m_dBattingAverage(dBattingAverage), m_nHomeRuns(nHomeRuns)    {    }};

推导图来表示继承,如下:


BaseballPlayer继承与Person,BaseballPlayer会自动从Person得到函数和变量。因此,BaseballPlayer对象会有5个成员变量(m_dBattingAverage and m_nHomeRuns from BaseballPlayer, and m_strName, m_nAge, and m_bIsMale from Person)。

通过下面的代码很容易验证这点:

#include <iostream>int main(){    // Create a new BaseballPlayer object    BaseballPlayer cJoe;    // Assign it a name (we can do this directly because m_strName is public)    cJoe.m_strName = "Joe";    // Print out the name    std::cout << cJoe.GetName() << std::endl;     return 0;}
结果为:Joe

An Employee derived class

下面是另外一个继承于Person的类,称为Employee类(员工类)。一个员工 “is-a” 人,所以使用继承是合适的。

// Employee publicly inherits from Personclass Employee: public Person{public:    std::string m_strEmployerName;    double m_dHourlySalary;    long m_lEmployeeID;     Employee(std::string strEmployerName, double dHourlySalary, long lEmployeeID)        : m_strEmployerName(strEmployerName), m_dHourlySalary(dHourlySalary),            m_lEmployeeID(lEmployeeID)    {    }     double GetHourlySalary() { return m_dHourlySalary; }    void PrintNameAndSalary()    {        std::cout << m_strName << ": " << m_dHourlySalary << std::endl;    }};
Employee 从Person继承了m_strName, m_nAge, m_bIsMale以及3个访问函数,并且添加了3个成员变量和自己的成员函数。注意的是成员函数PrintNameAndSalary同时使用了Employee自己的成员变量以及基类Person的成员变量。

派生表如下:

需要注意的是BaseballPlayer和Employee没有任何直接的联系,即使他们都继承了Person。


     Inheritance chains(继承链)

也有可能一个基类是另外一个类的派生类,即使如此也没什么值得特殊注意的,所有处理都按照之前的例子。

例如,一个公司管理人类(Supervisor),管理者也是员工,同样是一个人。如下:

class Supervisor: public Employee{public:    // This Supervisor can oversee a max of 5 employees    int m_nOverseesIDs[5];};
派生表如下:

所有Supervisor对象继承了Employee的变量和函数,并且添加了自己的变量m_nOverseesIDs.

通过构造这样的继承链,我们能创建可重用类的集合,它们具有一般性(顶层),并在每个层面的继承上逐步变得更具体。

总结

从一个基类继承意味着我们不必要重新定义基类中的相关信息。自动获得基类的成员变量和成员函数,然后简单的添加我们需要的额外的成员函数和变量。这样不仅能节省工作,也意味着如果我们更新基类(添加新函数以及bug修复),所有的派生类将会自动继承这些修改。

1 0
原创粉丝点击