目录
- 类继承
- 基类
- 派生一个类
- 构造函数访问权限
- 派生类与基类之间的特殊关系
- 完整demo
类继承
基类
#ifndef __TEST_1_H_
#define __TEST_1_H_
#include <iostream>
#include<string>
using namespace std;
typedef unsigned int uint;
//father class
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
#include "test_1.h"
//成员初始化列表语法
TableTennisPlayer:: TableTennisPlayer(const string & fn ,
const string & ln,bool ht ):firstname(fn),lastname(ln),hasTable(ht)
{}
void TableTennisPlayer::Name()const
{
std::cout << lastname << ", " << firstname << endl;
}
这里用到了string的默认构造函数
#include "test_1.h"
int main()
{
TableTennisPlayer player1{"Tara","Boomdea",false};
player1.Name();
if(player1.HasTable())
cout << "player1:has a table\n";
else
cout << "player1:hasn't a table\n";
return 0;
}
派生一个类
//derived class
class Rated_player : public TableTennisPlayer
{
private:
uint rating;
public:
Rated_player(uint r = 0,const string & fn = "none",const string & ln = "none",bool ht = false);
Rated_player(uint r,const TableTennisPlayer & tp);
uint Rating()const {return rating;}//内联函数
void ResetRating(uint r){rating = r;}
};
从上图可以看出,冒号指出Rated_player类的基类是TableTennisPlayer类,表明TableTennisPlayer是一个公有基类,这被称为公有派生,派生类对象包含基类对象。
使用公有派生,基类的公有成员将成为派生类的公有成员;基类的私有部分也将成为派生类的一部分,但只能通过基类的公有和保护方法访问。
- 需要在继承特性中添加什么?
1、需要自己的构造函数
2、可以根据需要添加额外的数据成员和成员函数
构造函数访问权限
派生类不能直接访问基类的私有成员,必须通过基类方法进行访问。
创建派生类对象时,程序首先创建基类对象,这意味着基类对象应当在程序进入派生类构造函数之前被创建。
C++使用成员初始化列表语法来完成这种工作。
如果不调用基类构造函数,程序将使用默认的基类构造函数。
有关派生类构造函数的要点如下:
- 首先创建基类对象
- 派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数
- 派生类构造函数应初始化派生类新增的数据成员
释放对象的顺序与创建对象的顺序相反,即首先执行派生类的析构函数,然后自动调用基类的析构函数。 - 成员初始化列表只能用于构造函数
派生类与基类之间的特殊关系
- 派生类对象可以使用基类的方法,条件是方法不是私有的
- 基类指针可以在不进行显式类型转换的情况下指向派生类对象;基类引用可以在不进行显式类型转换的情况下引用派生类对象
- 不可以将基类对象赋给派生类引用,如果这样做的话,派生类引用能够为基对象调用派生类方法,这样将出现问题。例如,将Rated_player::Rating()方法用于TableTennisPlayer对象是没有意义的,因为TableTennisPlayer对象没有rating成员。
完整demo
#ifndef __TEST_1_H_
#define __TEST_1_H_
#include <iostream>
#include<string>
using namespace std;
typedef unsigned int uint;
//father class
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;};
};
//derived class
class Rated_player : public TableTennisPlayer
{
private:
uint rating;
public:
Rated_player(uint r = 0,const string & fn = "none",const string & ln = "none",bool ht = false);
Rated_player(uint r,const TableTennisPlayer & tp);
uint Rating()const {return rating;}//内联函数
void ResetRating(uint r){rating = r;}
};
#endif
#include "test_1.h"
//成员初始化列表语法
TableTennisPlayer:: TableTennisPlayer(const string & fn ,
const string & ln,bool ht ):firstname(fn),lastname(ln),hasTable(ht)
{}
void TableTennisPlayer::Name()const
{
std::cout << lastname << ", " << firstname << endl;
}
Rated_player :: Rated_player(uint r,const string & fn,
const string & ln,bool ht) : TableTennisPlayer(fn,ln,ht),rating(r)
{
//rating = r;
}
Rated_player ::Rated_player(uint r,const TableTennisPlayer & tp)
: TableTennisPlayer(tp),rating(r)
{
//rating = r;
}
#include "test_1.h"
int main()
{
#if 0
TableTennisPlayer player1{"Tara","Boomdea",false};
Rated_player rplayer1{1140,"Mallory","Duck",true};
player1.Name();
rplayer1.Name();
if(player1.HasTable())
cout << "player1:has a table\n";
else
cout << "player1:hasn't a table\n";
if(rplayer1.HasTable())
cout << "rplayer1:has a table\n";
else
cout << "rplayer1:hasn't a table\n";
cout << "Rating:" << rplayer1.Rating() << endl;
Rated_player rplayer2 = {1122,player1};
rplayer2.Name();
cout << "Rating:" << rplayer2.Rating() << endl;
#endif
/*
基类指针或引用只能用于调用基类的方法
*/
Rated_player rplayer(1140,"Mallory","Duck",true);
TableTennisPlayer & rt = rplayer;
TableTennisPlayer * pt = &rplayer;
rt.Name();
pt->Name();
return 0;
}