C++:类的设计————公有继承

1.继承的概念

继承是c++的特性,其含义是从已有的类派生出新的类,而派生的类继承了基类的一些私有成员和成员函数。

公有继承是最为常用的继承方式。

2.公有继承的特点

派生类的对象继承了基类的私有成员,但是不可以直接访问(派生类继承基类的实现)

派生类的对象可以使用基类的成员方法(派生类继承了基类的接口)。

继承的使用必须基于继承的这两个特点,举一个简单的例子。

假设有基类Player,描述一个运动员的姓名属性。

class Player
{
    private:
        std::string firstname;
        std::string lastname;
    public:
        Player(const std::string & fname = "none", const std::string & lname = "none") : firstname(fname), lastname(lname) {};
        void name() const;
        ~Player();
};

我们想设计一个新的类,这个类中除了运动员的姓名还要加入新的属性,运动员的排名。

因为这个新的类比起Player只多了rating属性和一些成员方法,那么我们就可以利用Player这个类来派生出新的类,提高代码的重用性。

class RatedPlayer : public Player
{
    private:
        unsigned int rating;
    public:
        RatedPlayer(const unsigned int r = 0, const std::string & fname = "none", const std::string & lname = "none");
        RatedPlayer(unsigned int r, const Player & pl);
        void reset_rating(unsigned int r = 0) {  rating = r ; };
};

公有继承的语法很简单,在派生类(RatedPlayer)的后边加冒号(:)后跟关键字public+基类名(Player)

3.需要在继承的特性中添加什么

派生类需要自己的构造函数(非常重要)。

派生类可以根据自己的需要添加新的私有成员和成员函数。

派生类的构造函数尤为重要,理解派生类的构造函数对于继承这一概念的了解会有很大帮助。

下面给出派生类的构造函数的函数体然后说明。

RatedPlayer::RatedPlayer(const unsigned int r, const std::string & fname, const std::string & lname) : Player(fname, lname), rating(r) {};

我们可以看出,在构造派生类的时候,我们使用了基类的构造函数,那么这是为什么呢?

首先,派生类不可以直接访问基类的私有成员,必须通过基类的方法,所以说RatedPlayer中的firstname、lastname只能通过基类的构造函数来进行初始化。

其次,创建派生类对象的时候,程序应当首先创建基类对象,因为没有基类哪来的派生类呢?

所以说,RatedPlayer中的构造函数中的Player(fname,lname)可以理解成先构造了基类对象,在这基础上又添加派生类对象的私有成员初始化。

那么,如果不调用基类的构造函数会怎么样呢?

即:

RatedPlayer::RatedPlayer(const unsigned int r, const std::string & fname, const std::string & lname)
{
    rating = r;
}

会怎么样呢?

注意,编译器始终遵循先创建基类对象后创建派生类对象的原则,所以说,上述代码等价于:

RatedPlayer::RatedPlayer(const unsigned int r, const std::string & fname, const std::string & lanme) : Player()
{
    rating = r;
}  

调用基类对象的默认构造函数,如果不存在默认构造函数,那么就会出错。

除非要使用默认基类构造函数,否则应当进行显示调用。

公有继承要点如下:

•在创建派生类对象的时候应当首先创建基类对象。

•派生类构造函数应当通过成员初始化列表的方式将基类信息(即基类中的私有成员)传递给基类的构造函数。

•派生类构造函数应初始化派生类新增的数据成员。

其次还要着重说明一下,那就是派生类和基类之间的特殊关系。

除了派生类可以使用基类的方法这一关系外,还有三条重要的关系。

•基类指针可以在不进行显示转换的情况下指向派生类对象

•基类引用可以在不进行显示转换的情况下指向派生类引用

•同样的,可以将派生类对象赋值给基类对象而无需进行cast转换

#include "Player.h"
#include <iostream>
int main()
{
    RatedPlayer player(100,"Bob", "Brown");
    Player & pl = player;
    Player * p = &player;

    pl.name();
    p->name();
    getchar();
    return 0;
}

这三个特性非常好,我们可以只建立一种基类类型的指针数组存储派生类和基类对象批量处理

实际上,公有继承建立一种is-a关系,即派生类是一种基类的特殊情况。

 

posted @ 2015-03-29 16:00  SixDayCoder  阅读(2764)  评论(0编辑  收藏  举报