面向对象编程的主要目的之一是提供可重用的代码。开发新项目,尤其是当项目分庞大时,重用经过测试的代码比重新编写代码要好得多。使用已有的代码可以节省时间,由于已有的代码已被使用和测试过,因此有助于避免在程序中引入错误。另外,必须考虑的细节越少,便越能专注于程序的整体策略。
传统的C函数库通过预定义、预编译的函数(如strlen()和rand()可以在程序中使用这些函数)提供了可重用性。很多厂商都提供了专用的C库,这些专用库提供标准C库没有的函数。
目前,很多厂商提供了类库,类库由类声明和实现构成。因为类组合了数据表示和类方法,因此提供了比函数库更加完整的程序包。例如,单个类就可以提供用于管理对话框的全部资源。通常,类库是以源代码的方式提供的,这意味着可以对其进行修改,以满足需求。
然而C++提供了比修改代码更好的方法来扩展和修改类。这种方法叫作类继承,它能够从已有的类派生出新的类,而派生类继承了原有类(称为基类)的特征,包括方法。正如继承一笔财产要比自己白手起家容易一样,通过继承派生出的类通常比设计新类要容易得多。
下面是可以通过继承完成的一些工作。
1. 可以在已有类的基础上添加功能。例如,对于数组类,可以添加数学运算。
2. 可以给类添加数据。例如,对于字符串类,可以派生出一个类,并添加指定字符串显示颜色的数据成员。
3. 可以修改类方法的行为。例如对于代表提供给飞机乘客的服务的Passenger 类,可以派生出提供更高级别服务的FirstClassPassenger类。
当然,可以通过复制原始类代码,并对其进行修改来完成上述工作,但继承机制只需提供新特性,
甚全不需要访问源代码就可以派生出类。因此,如果购买的类库只提供了类方法的头文件和编译后代码,仍可以使用库中的类派生出新的类。而且可以在不公开实现的情况下将自己的类分发给其他人,同时允许他们在类中添加新特性。
继承是一种非常好的概念,其基本实现非常简单。但要对继承进行管理,使之在所有情况下都能正常工作,则需要做一些调整。
一个简单的基类从一个类派生出另一个类时,原始类称为基类,继承类称为派生类。为说明继承,首先需要一个基类。Webtown俱乐部决定跟踪乒乓球会会员。作为俱乐部的首席程员,需要设计一个简单的 TableTennisPlayer类。
TableTennisPlayer类只是记录会员的姓名以及是否有球桌。有两点需要说明。首先,这个类使用标准string类来存储姓名,相比于使用字符数组,这更方便更灵活更安全。其次,构造函数使用了成员初始化列表语法。
派生一个类
Webtown俱乐部的一些成员曾经参加过当地的乒乓球锦标赛,需要这样一个类,它能包括成员在比赛中的比分。与其从零开始不如从 TableTennisClass 类派生出一个类。首先将 RatedPlayer 类声明为从TableTennisClass类派生而来:
?? ?class RatePlayer : public TableTennisPlayer
?? ?{
?? ? ?...
?? ?};
?? ?
冒号指出 RatedPlayer类的基类是 TableTennisplayer 类。上述特殊的声明头表明?TableTennisPlayer 是一个公有基类,这被称为公有派生。派生类对象包含基类对象。使用公有派生,基类的公有成员将成为派生类的公有成员:基类的私有部分也将成为派生类的一部分,
但只能通过基类的公有和保护方法访问。
上述代码完成了哪些工作呢?Ratedplayer对象将具有以下特征:
1. 派生类对象存储了基类的数据成员(派生类继承了基类的实现:
2. 派生类对象可以使用基类的方法(派生类继承了基类的接口)。
因此,RatedPlayer 对象可以存储运动员的姓名及其是否有球桌。
另外,RatedPlayer 对象还可以使用TableTennisPlayer 类的 Name()、
hasTable()和 ResetTable()方法。
需要在继承特性中添加什么呢?
1. 派生类需要自己的构造函数。
2. 派生类可以根据需要添加额外的数据成员和成员函数。
在这个例子中,派生类需要另一个数据成员来存储比分,还应包含检索比分的方法和重置比分的方法。因此,类声明与下面类似:
class RatePlayer : public TableTennisPlayer
{
private:
?? ?unsigned int rating;?? ??? ?// 增加的一个成员变量
public:
?? ?RatePlayer(unsigned int r=0, const string &fn = "none",
?? ??? ?const string& ln = "none",
?? ??? ?bool ht = false);
?? ?RatePlayer(unsigned int r=0, const TableTennisPlayer& tp);
?? ??? ?
?? ?unsigned int Rating() const {return rating;} ?? ? //新增的方法
?? ?void ResetRating(unsigned int r){ rating = r; } ?//新增的方法
};
示例源码:
// Len_TableTennisPlayer.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <string>
#include <iostream>
using namespace std;
//
//
// 基类
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; }
};
TableTennisPlayer::TableTennisPlayer(const string &fn,
const string& ln, bool h) :firstname(fn), lastname(ln), hasTable(h)
{
}
void TableTennisPlayer::Name() const
{
cout << lastname << endl;
}
//
//
// 派生类
class RatePlayer : public TableTennisPlayer
{
private:
unsigned int rating; // 增加的一个成员变量
public:
RatePlayer(unsigned int r = 0, const string &fn = "none",
const string& ln = "none", bool ht = false)
{
};
RatePlayer(unsigned int r, const TableTennisPlayer& tp)
{};
unsigned int Rating() const { return rating; } //新增的方法
void ResetRating(unsigned int r){ rating = r; } //新增的方法
};
//
//
int _tmain(int argc, _TCHAR* argv[])
{
return 0;
}