标签:style blog http color 使用 os io strong
一、基类和派生类
很多时候,一个类的对象也“是”另一个类的对象,如矩形是四边形,在C++中,矩形类Rectangle可以由四边形类Quad继承而来,于是,四边形类Quad是基类,矩形类Rectangle是派生类。但是如果说四边形一定是矩形显然不对。几个简单的基类和派生类的例子:
基类 派生类
食物 米饭、面条、水饺
交通工具 汽车、火车、飞机
国家 中国、美国、西班牙
可以看出,每个派生类的对象都是基类的一个对象,并且一个基类可以有很多派生类。继承关系构成一种树状层次结构。基类和派生类存在这种层次关系,如下图:
下面用程序实例来说明:
建立一个乒乓球会员的类TableTennisPlayer类:
1 #ifndef TABTEN_H_
2 #define TABTEN_H_
3 #include <string>
4 using std::string;
5 //一个简单的基类
6 class TableTennisPlayer
7 {
8 private:
9 string firstname;
10 string lastname;
11 bool hasTable;
12 public:
13 TableTennisPlayer (const string & fn = "none",
14 const string & ln = "none", bool ht = false);
15 void Name() const;
16 bool HasTable() const {return hasTable;}
17 void ResetTable(bool v) {hasTable = v;}
18 };
19
20 #endif
1 #include <iostream>
2 #include "tabten.h"
3
4 TableTennisPlayer::TableTennisPlayer (const string & fn,
5 const string & ln, bool ht) : firstname(fn), lastname(ln),hasTable(ht) {}
6
7 void TableTennisPlayer::Name() const
8 {
9 std::cout << lastname << ", " << firstname;
10 }
TableTennisPlayer类只记录会员的姓名以及是否有桌球。假设一些会员参加过锦标赛,则需要这样一个类,它能包括会员在比赛中的比分。我们要重新新建一个类吗?显然不用,这时候只需从TableTennisPlayer类派生出一个类,假设为RatedPlayer
class RatedPlayer : public TableTennisPlayer
{
...
};
冒号表示RatedPlayer类的基类是TableTennisPlayer类,public 表明TableTennisPlayer是一个公有基类,这被称为公有派生。
使用公有派生,基类的公有成员将成为派生类的公有成员;基类的私有部分也将成为派生类的一部分,但是只能通过基类的公有(public)和保护(protected)方法访问。
RatedPlayer对象将具有以下特征:
派生类还需要做:
添加派生类的头文件如下:
1 #include <iostream>
2 #include "tabten.h"
3
4 TableTennisPlayer::TableTennisPlayer (const string & fn,
5 const string & ln, bool ht) : firstname(fn), lastname(ln),hasTable(ht) {}
6
7 void TableTennisPlayer::Name() const
8 {
9 std::cout << lastname << ", " << firstname;
10 }
11
12 class RatedPlayer : public TableTennisPlayer
13 {
14 private:
15 unsigned int rating; //添加数据成员
16 public:
17 //派生类的构造函数必须给新成员(如果添加了的话)和基类的成员提供数据
18 RatedPlayer (unsigned int r = 0, const string & fn = "none",
19 const string & ln = "none", bool ht = false);
20 RatedPlayer (unsigned int r, const TableTennisPlayer & tp);
21 unsigned int Rating() const {return rating;}//添加方法
22 void ResetRating (unsigned int r) {rating = r;}//添加方法
23 };
1 #include <iostream>
2 #include "tabten.h"
3
4 TableTennisPlayer::TableTennisPlayer (const string & fn,
5 const string & ln, bool ht) : firstname(fn), lastname(ln),hasTable(ht) {}
6
7 void TableTennisPlayer::Name() const
8 {
9 std::cout << lastname << ", " << firstname;
10 }
11
12 RatedPlayer::RatedPlayer (unsigned int r, const string & fn,
13 const string & ln, bool ht) : TableTennisPlayer(fn, ln, ht)
14 {
15 rating = r;
16 }
17 RatedPlayer::RatedPlayer (unsigned int r, const TableTennisPlayer & tp)
18 : TableTennisPlayer(tp), rating(r){}
派生类的构造函数必须给新成员(如果添加了的话)和基类的成员提供数据。派生类不能直接访问基类的私有成员,而必须通过基类方法访问,例如RatedPlayer构造函数不能直接设置继承的成员firstname, lastname和hasTable, 而必须使用基类的公有方法来访问私有的基类成员。
有关派生类构造函数的要点如下:
二、使用派生类
1 #include <iostream>
2 #include "tabten.h"
3
4 int main ()
5 {
6 using std::cout;
7 using std::endl;
8 TableTennisPlayer player1("Tara", "Boomdea", false);
9 RatedPlayer rplayer1(1300, "Mallory", "Duck", true);
10 rplayer1.Name();//派生类调用基类的方法
11 cout << ( rplayer1.HasTable() ? (": has a table\n") : ("hasn‘t a table\n") );
12 player1.Name();
13 cout << ( rplayer1.HasTable() ? (": has a table\n") : ("hasn‘t a table\n") );
14 cout << "Name: ";
15 rplayer1.Name();
16 cout << "; Rating: " << rplayer1.Rating() << endl;
17
18 //用基类对象初始化派生类
19 RatedPlayer rplayer2(1212, player1);
20 cout << "Name: ";
21 rplayer2.Name();
22 cout << "; Rating: " << rplayer2.Rating() << endl;
23
24 return 0;
25 }
三、protected数据的继承
当基类中的成员数据为protected时,派生类就可以直接访问,而不用通过基类的公共方法去访问这些protected数据,简单来说,派生类可以直接继承protected数据成员,可以免去调用成员函数的开销,
使程序的性能稍稍有所提高。
在一个类的声明中,一个良好的类声明顺序最好是先声明public,然后是protected成员,最后是private成员。
使用protected数据注意的事项
多数情况下,使用private数据成员是更好的软件工程的方法,虽然protected数据的继承使程序的性能稍稍有所提高,但是代码优化就交给编译器去做好了,这样的话代码更易于维护、修改和调试,一句话,除非万不得已,尽量不使用protected数据的继承。
“程序员应该致力于编写符合软件工程原则的代码,而将优化的问题留给编译器去做”。一条好的准则是:“不要怀疑编译器”。
四、补充
派生类不会继承基类的构造函数、析构函数和重载的赋值运算符,但是派生类可以调用基类的构造函数、析构函数和重载的赋值运算符函数。
当由基类派生出一个类时,继承基类的方式三种,即public继承、protected继承和private继承。但实际情况是,一般很难采用private继承和protected继承,而且使用时需十分小心。
下图是派生类对基类成员的访问权限的一个总结:
标签:style blog http color 使用 os io strong
原文地址:http://www.cnblogs.com/90zeng/p/Cpp_derive.html