【C++】面向对象编程(四)派生类

派生类

由两部分构成:

  1. 基类构成的子对象;
  2. 派生类的部分。
cpp 复制代码
#include"num_sequence.h"//基类的定义必须已经存在

class Fibonnacci : public num_sequence{
public:
	//...
};
  • 必须为从基类继承而来的每个纯虚函数提供对应的实现;
  • 必须声明自己类的专属成员
cpp 复制代码
class Fibonacci: public num_sequence{
public:
	Fibonnacci(int len=1, int beg_pos=1):_length(len), _beg_pos(beg_pos){}
	
	virtual int elem(int pos) const;
	virtual const char* what_am_i()const{return "Fibonacci";}
	virtual ostream& print(ostream &os=cout) const;
	int length() const{return _length;}
	int beg_pos() const {return _beg_pos;}

protected:
	virtual void gen_elems(int pos) const;
	int _length;
	int _beg_pos;
	static vector<int> _elems;

通过基类的接口无法访问length()和beg_pos():

cpp 复制代码
num_sequence *ps=new ...;//举例
ps->what_am_i();//ok:通过虚函数机制,调用Fibonacci::what_am_i();
ps->max_elems();//ok:调用继承而来的num_sequence::max_elems();
ps->length();//错误:length()并非基类提供的接口中的一员;
delete ps;//ok:通过虚函数机制调用Fibonacci的析构函数。

解决:

cpp 复制代码
//在基类num_sequence加上两个纯虚函数
//length()和beg_pos()自动成为虚函数(无需关键字virtual)
virtual int length()  const = 0;
virtual int beg_pos() const = 0; 
  • 派生类的虚函数必须精确吻合基类中的函数原型;
  • 在类之外对虚函数进行定义时,不必指明关键字virtual;
  • 从基类继承而来的public成员和protected成员,都可被视为派生类自身拥有的成员,同样遵循访问层级的原则:
  • public:开放给派生类的用户使用;
  • protected:只能给后续饿顶派生类使用,无法给目前这个派生类使用;
  • private:完全无法让派生类使用。
  • 跳过虚函数机制:用类作用域运算符指明调用对象(在编译时即解析,不必等到程序运行时解析);
cpp 复制代码
int Fibonacci::elem(int pos)const
{
	if(!check_integrity(pos,_elems.size() ))
		return 0;
	
	if(pos>_elems.size())
		Fibonacci::gen_elems(pos);
	
	return _elems[ pos-1 ];
} 
  • 每当派生类有某个成员和其基类的成员同名,便会掩盖住基类的那份成员,前提是在派生类里声明了该同名成员;
  • 如果要在派生类内使用继承来的成员,必须利用类作用域运算符加以限定:
cpp 复制代码
class Fibonacci: public num_sequence{
//...
protected:
	bool check_integrity(int pos)const;
	//...
};

int Fibonacci::elem(int pos)const
{
	if(!check_integrity(pos))
		return 0;
	//...
}

inline bool Fibonacci::check_integrity(int pos)const
{
	if(!num_sequence::check_integrity(pos))
		return false;
	
	if(pos>_elems.size())
		Fibonacci:gen_elems(pos);
	
	return true;
}

在基类中,check_integrity()并未被视为虚函数,用基类指针/引用调用,解析出来的都是基类的那一份:

解决:

重新定义check_integrity(),令它拥有两个参数:(派生类的成员函数不改变)

cpp 复制代码
bool num_sequence::check_integrity(int pos, int size)
{
		if( pos <= 0 || pos > _max_elems )
		{
			//和之前相同
		}
		
		if (pos > size )
			//gen_elems()是通过虚拟机制调用
			gen_elems( pos );
			
	return true;
}
相关推荐
zwjapple5 分钟前
typescript里面正则的使用
开发语言·javascript·正则表达式
小五Five7 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
前端每日三省8 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
凡人的AI工具箱22 分钟前
15分钟学 Go 第 60 天 :综合项目展示 - 构建微服务电商平台(完整示例25000字)
开发语言·后端·微服务·架构·golang
做人不要太理性25 分钟前
【C++】深入哈希表核心:从改造到封装,解锁 unordered_set 与 unordered_map 的终极奥义!
c++·哈希算法·散列表·unordered_map·unordered_set
程序员-King.33 分钟前
2、桥接模式
c++·桥接模式
chnming198737 分钟前
STL关联式容器之map
开发语言·c++
进击的六角龙39 分钟前
深入浅出:使用Python调用API实现智能天气预报
开发语言·python
檀越剑指大厂39 分钟前
【Python系列】浅析 Python 中的字典更新与应用场景
开发语言·python
湫ccc1 小时前
Python简介以及解释器安装(保姆级教学)
开发语言·python