ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第13章 类继承

2022-07-10 14:33:50  阅读:183  来源: 互联网

标签:13 const string 继承 基类 派生类 构造函数 TableTennisPlayer


<c++ primer plus>第六版

目录

13 类继承

  1. 面向对象编程的主要目的之一是提供可重用的代码.
  2. 传统的C函数库通过预定义/预编译的函数(strlen(), rand()等)提供可重用性. 但函数库也有局限, 就是无法根据特定需求对函数进行扩展和修改.
  3. c++类提供了更高层次的重用性, 可以通过类继承对类进行扩展和修改.

13.1 一个简单的基类

TableTennisPlayer类

.h文件, 用于定义class, 函数原型等

//tabtenn0.h -- a table tennis base class

#ifndef TABTENN0_H_
#define TABTENN0_H_

#include <string>

using std::string;

class TableTennisPlayer
{
    private:
        string firstname;
        string lastname;
        bool hasTable;
    public:
        TableTennisPlayer(
            const string &fn = "none",
            const string &ln = "none",
            bool ht = false
        );
        void Name() const;
        bool HasTable() const{
            return hasTable;
        };
        void ResetTable(bool v){
            hasTable = v;
        };

};

#endif

.cpp文件用于定义class中的函数

//tabtenn0.cpp -- simple base class methods

#include "tabtenn0.h"
#include <iostream>

//TableTennisPlayer::TableTennisPlayer(const string &fn, const string &ln, bool ht): firstname(fn), lastname(ln), hasTable(ht)
//{
//}
TableTennisPlayer::TableTennisPlayer(const string &fn, const string &ln, bool ht)
{
    firstname = fn;
    lastname = ln;
    hasTable = ht;
}

void TableTennisPlayer::Name() const
{
    std::cout << lastname << ", " << firstname;
}

使用TableTennisPlayer这个类

// usett0.cpp -- using a base class
#include <iostream>
#include "tabtenn0.h" //注意这里只include .h文件, 不include .cpp文件, 只需要class定义及函数原型即可.

int main(void)
{
    using std::cout;
    TableTennisPlayer p1("Chuck", "Blizzard", true);
    TableTennisPlayer p2("Tara", "Boomdea", false);

    p1.Name();
    if (p1.HasTable()) 
        cout << ": has a table.\n";
    else
        cout << ": hasn't a table.\n";

    p2.Name();
    if (p2.HasTable()) 
        cout << ": has a table.\n";
    else
        cout << ": hasn't a table.\n";

    return 0;
}

编译+运行

g++ usett0.cpp tabtenn0.cpp -o usett0.exe #注意, 编译文件列表中没有.h文件
usett0.exe

13.1.1 派生一个类

//以TableTennisPlayer为基类, 派生一个类RatedPlayer
class RatedPlayer : public TableTennisPlayer
{
private:
    unsigned int rating; //add a data member
public:
    RatedPlayer(
        unsigned int r=0,
        const string &fn="none",
        const string &ln="none",
        bool ht=false
    );
    RatedPlayer(
        unsigned int r=0,
        const TableTennisPlayer &tp
    );

    unsigned int Rating() const{ //add a method
        return rating;
    }
    void ResetRating(unsigned int r){ //add a method
        rating=r;
    }
}

注意: 构造函数必须给新成员(如果有的话)和继承的成员提供数据.

13.1.2 构造函数: 访问权限

派生类不能直接访问基类的私有成员, 需要通过基类方法来访问.
所以一般来说, 派生类的构造函数必须使用基类的构造函数.

创建派生类对象时, 程序产生创建基类对象. c++使用成员初始化列表语法来完成这种工作.
例: 一个派生类的构造函数

RatedPlayer::RatedPlayer
(
    unsigned int r,
    const string &fn,
    const string &ln,
    boot ht
): TableTennisPlayer(fn, ln, ht) //在成员初始化列表中调用基类的构造函数.
{
    rating = r;
}

如果上述构造函数中没有显式地调用基类的构造函数, 则将使用基类的默认构造函数.
即:

RatedPlayer::RatedPlayer
(
    unsigned int r,
    const string &fn,
    const string &ln,
    boot ht
) //在成员初始化列表中没显式调用基类的构造函数.
{
    rating = r;
}

等价于:

RatedPlayer::RatedPlayer
(
    unsigned int r,
    const string &fn,
    const string &ln,
    boot ht
): TableTennisPlayer() //等价于使用默认构造函数
{
    rating = r;
}

对于如下代码

RatedPlayer::RatedPlayer
(
    unsigned int r,
    const TableTennisPlayer &tp
): TableTennisPlayer(tp) //传给基类的变量tp的类型是TableTennisPlayer&, 所以将调用基类的复制构造函数.
{
    rating = r;
}

13.1.3 使用派生类

13.1.4 派生类和基类之间的特殊关系

  1. 派生类可以使用基类的方法(前提是该方法不能是私有方法).
  2. 基类指针可以在不进行显式类型转换的情况下指向派生类对象(但只能访问基类的方法).
  3. 基类引用可以在不进行显式类型转换的情况下引用派生类对象.
RatedPlayer rplayer1(1140, "Mallory", "Duck", true);
TableTennisPlayer & rt = = rplayer;  //基类引用, 引用派生类对象
TableTennisPlayer * pt = = &rplayer; //基类指针, 指向派生类对象
  1. 如果一个函数的参数是基类引用(或基类指针), 则这个函数也可以接受派生类引用(或派生类指针)作为参数.
  2. 可以将基类对象初始化为派生类对象.
RatedPlayer olaf1(...); //派生类对象
TableTennisPlayer olaf2(olaf1); //用派生类对象 对 基类对象 进行初始化.
  1. 将派生对象赋值给基类对象, 这种情况下程序将使用隐式重载赋值运算符.
RatedPlayer olaf1(...); //派生类对象
TableTennisPlayer winner; //基类对象.
winner = olaf1; //将派生对象赋值给基类对象, 将使用隐式重载赋值运算符:
                //TableTennisPlayer &operator=(const TableTennisPlayer &) const

13.2 继承: is-a关系

c++有3种继承方式: 公有继承, 保护继承, 私有继承.
其中, 公有继承是最常用的方式, 它建立一种is-a关系, 即派生类对象也是一个基类对象, 如果一个操作可以在基类对象上执行, 则这个操作也可以在派生对象上执行.

标签:13,const,string,继承,基类,派生类,构造函数,TableTennisPlayer
来源: https://www.cnblogs.com/gaiqingfeng/p/16463157.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有