派生类
由两部分构成:
- 基类构成的子对象;
- 派生类的部分。
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;
}