【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;
}
相关推荐
zh路西法14 分钟前
【玩转VLA具身智能机械臂】(四):点云分割与 OBB 夹取——从 PCA 失效到主动扫描
c++·机械臂·pca·vla·planner·obb·moveit2
小灰灰搞电子19 分钟前
Rust Attribute(属性标记)完整整理
开发语言·后端·rust
爱和冰阔落35 分钟前
【Linux】条件变量为什么必须配合互斥锁:从 pthread_cond_wait 到阻塞队列
linux·运维·c++·缓存·中间件·安卓
tedcloud12336 分钟前
God‘s Eye View 怎么搭建?在云服务器上部署一个实时 3D 地球可视化平台
linux·服务器·开发语言·后端·rust
初願致夕霞42 分钟前
Linux 进程间通信(IPC)机制详解:管道、FIFO 与 System V 共享内存
linux·服务器·c++
Tairitsu_H1 小时前
[C++] C++11 Lambda与包装器深度解析
开发语言·c++·c++11·lambda·包装器
sunoo-2291 小时前
【51单片机实战】温控下位机完整实现:DS18B20采集 + 自定义二进制串口协议 + PWM声光告
笔记·学习·51单片机·串口
傲世仙尊1 小时前
从磁盘硬件到Ext文件系统-Linux磁盘级文件系统学习笔记
linux·运维·服务器·开发语言·c++
小羊没烦恼!1 小时前
Memory 记忆设计讨论:为什么 Agent Memory 不能只靠向量数据库?
java·开发语言·windows·算法·c#
FlightYe1 小时前
音视频修炼之编码器(一):AVC、HEVC编码器内部
android·linux·c++·音视频