C++继承和派生

一、继承的含义

  1. 所谓"继承"就是在一个已存在的类的基础上,再建立一个新类
  2. 从已有的类派生出新的类,派生类就继承了原有类(基类)的特征,包括成员和方法
  3. 通过继承可以完成下面的一些功能
    3.1 可以在已有类的基础上添加新功能,如对于数组类,可以添加数学计算
    3.2可以给类添加数据成员,如对于字符串类,可以派生出一个类,并添加指定成员表示颜色
    3.3可以修改类方法的行为,如对于普通英雄类,可以派生出拥有更丰富技能的近战英雄类

二、继承的优点

在这里插入图片描述

  1. 基类定义公共内容,方便统一修改(代码的可重用)
  2. 重定义基类的成员函数
  3. 添加新类,新成员方便

注意:

  1. 派生类对象存储了基类的数据成员,即派生类继承了基类的实现
  2. 派生类对象可以使用基类的非私有函数,即派生类继承了基类的接口
  3. 派生类需要自己的构造函数
  4. 派生类可以根据需要添加额外的数据成员和函数

三、基类和派生类

  1. 定义子类对象:如果派生类中不实现某个非私有成员方法,会默认调用基类方法;如果派生类实现了基类某个非私有方法,那就会调用子类方法
    Warrior warrior;
    warrior.Move();	//子类实现了就调用子类的,没实现就默认调用基类的实现
    
  2. 定义基类指针指向派生类对象 ,那此时才会调用基类的方法,但是不能调用派生类方法
    //这里调用基类Move
    Hero *hero = new Warrior();		//定义基类指针指向派生类对象
    hero->Move();
    delete hero;
    
  3. final关键字,在类名后面修饰,表示该类不能做为基类被其他类继承
    class A final
    {
    };
    class B : public A	//此时编译器会报错误
    {
    };
    

四、有关基类和派生类构造和析构

  1. 实例化派生类对象时,首先会调用基类的构造函数,再调用派生类的构造函数(析构的顺序和构造的顺序相反,即先调用派生类的析构函数,再调用派生类的析构函数)
  2. 实例化派生类对象时,如果没有显示的调用基类的构造函数,就会调用基类的默认构造函数
  3. 派生类构造应通过成员初始化列表将基类信息传递给基类构造
  4. 应该在派生类构造中初始化派生类新增的数据成员

五、派生类和基类之间的特殊关系小结

  1. 派生类对象可以使用基类的非私有成员函数和变量
  2. 基类指针可以在不进行显示类型转换的情况下指向派生类对象(基类指针可以直接指向派生类对象)
  3. 可以将派生类对象赋值给基类对象,程序将使用隐式重载赋值运算符

注意:

  1. 基类指针或引用只能调用基类函数,并不能调用派生类函数
  2. 不可以将基类对象和地址赋值给派生类引用和对象,即不能够做逆操作
  3. 派生类引用/指针需要强制转换才可以转换成基类对象或引用

六、派生类成员的访问控制(最高访问权限)

  1. 公有继承:基类的共有成员和受保护成员,在派生类中保持原来的访问属性,其私有成员仍为基类所独有
  2. 私有继承:基类的公有成员和受保护成员,在派生类中成为了私有成员,私有成员仍为基类所独有
  3. 受保护继承:基类公有成员和受保护成员,在派生类中成了受保护成员,私有成员仍为基类所独有
//.h文件
class Hero
{
public:
	Hero();
	Hero(const std::string &nickName, int level, int maxLife, int currLife);
	~Hero();

	/*基类中的移动方法*/
	void Move();

	friend ostream & operator << (ostream &out, const Hero &hero);

	/*关于const关键字:
	1.在方法前:表示返回值是一个const常量 - 只读
	2.在方法后:表示方法不可以修改类成员的值
	*/
	inline const string &GetNickName() const { return m_NickName; }
	inline int GetLevel() const { return m_Level; }
	inline int GetMaxLife() const { return m_MaxLife; }
	inline int GetCurrLife() const {return m_CurrLife;}

	inline void SetNickName(const string &nickName) { m_NickName = nickName; }
	inline void SetLevel(int level) { m_Level = level; }
	inline void SetMaxLife(int maxLife) { m_MaxLife = maxLife; }
	inline void SetCurrLife(int currLife) { m_CurrLife = currLife; }

private:
	string m_NickName;
	int m_Level;
	int m_MaxLife;
	int m_CurrLife;
};
//cpp 文件
#include "stdafx.h"
#include "Hero.h"

Hero::Hero():Hero("默认英雄",1,100,100)		//第一看这种操作(可以调用自己的构造函数)
{
	cout << "调用了Hero的默认构造函数" << endl;
}
Hero::Hero(const string &nickName, int level, int maxLife, int currLife):
	m_NickName(nickName),m_Level(level),m_MaxLife(maxLife),m_CurrLife(currLife)
{
	cout << "调用了Hero的4个参数默认构造函数" << endl;
}

Hero::~Hero()
{
}
void Hero::Move()
{
	cout << "普通英雄" << m_NickName << "正在奔跑在大路上" << endl;;
}
ostream & operator << (ostream &out, const Hero &hero)
{
	out << "昵称:" << hero.m_NickName << "\n"
		<< "等级:" << hero.m_Level << "\n"
		<< "最大生命:" << hero.m_MaxLife << "\n"
		<< "当前生命:" << hero.m_CurrLife << endl;
	return out;
}
//.h文件
#include "Hero.h"
/*战士类*/
class Archmage;
class Warrior : public Hero
{
public:
	Warrior();
	Warrior(const std::string &nickName,int phyAttack);
	~Warrior();

	void Move();
	void HiSunZi();
	void XiaoQuanQuan(Warrior &other);
	void XiaoQuanQuan(Archmage &other);

private:
	int m_PhysicalAttack;	//物理攻击
};

//.cpp 文件
#include "stdafx.h"
#include "Warrior.h"
#include "Archmage.h"

Warrior::Warrior() :Hero("默认战士",1,100,100)
{
	cout << "Warrior的构造函数" << endl;
}
Warrior::Warrior(const string &nickName, int phyAttack) : Hero(nickName,1,100,100),m_PhysicalAttack(phyAttack)
{
}

Warrior::~Warrior()
{
}
void Warrior::Move()
{
	//派生类中不能直接访问基类的私有成员
	cout << "战士 《" << GetNickName() << "》背着一大堆近战武器正在靠近" << endl;
}
void Warrior::HiSunZi()
{

}
void Warrior::XiaoQuanQuan(Warrior &other)
{
	cout << GetNickName() << "发出了一剂流星锤" << endl;
	cout << other.GetNickName() << "受伤倒地" << endl;
	other.SetCurrLife(other.GetCurrLife() - 10);
}
void Warrior::XiaoQuanQuan(Archmage &other)
{
	cout << GetNickName() << "为了攻击法师,使了一招野蛮冲撞" << endl;
	cout << "法师" << other.GetNickName() << "受到重创" << endl;
	other.SetCurrLife(other.GetCurrLife() - 10);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值