C++ 类继承

发布时间:2024年01月05日

面向对象编程的主要目的之一是提供可重用的代码。开发新项目,尤其是当项目分庞大时,重用经过测试的代码比重新编写代码要好得多。使用已有的代码可以节省时间,由于已有的代码已被使用和测试过,因此有助于避免在程序中引入错误。另外,必须考虑的细节越少,便越能专注于程序的整体策略。


传统的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;
}

文章来源:https://blog.csdn.net/wendyWJGU/article/details/135415986
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。