C++的封装(九):把多态装进盒子

C++语言用虚函数实现多态,比如,狼和鳄鱼都会咬(人),但是以不同的方式。实现代码大致如下,

class animal {
public:
	virtual void bite();
};
class wolf: public animal {
public:
	virtual void bite();
};

class crocodile: public animal {
public:
	virtual void bite();
};

通过这样一个继承链和虚函数实现以后,可以狼和鳄鱼的对象可以以animal的面目出现在程序中,但仍然可以保持各自的个性bite()。这个就是多态。

如果把这个多态再封装一下, 把上文的class animal改名animal_imp,而狼和鳄鱼依然继承animal_imp,变成这样:

class animal {
private:
	animal_imp *imp;
public:
	animal(animal_imp *imp) :imp(imp){}
	void bite() {imp->bite();}
};

现在,程序的其他部分引用这个改编的animal的时候,不需要考虑多态,而运行时实际上狼和鳄鱼还是保持了自己的个性bite()。

当animal类继续扩展,更多的公共属性出现在animal类中,这些属性跟 bite()无关,比如,

class animal {
private:
	animal_imp *imp;
	int h;
	int w;
public:
	animal(animal_imp *imp) :imp(imp){}
	void bite() {imp->bite();}

	int height();
	int weight();
	void grow();
};

出现差异的地方,即狼和鳄鱼的个性bite()被隐藏。复杂性得到了控制。多态出现的范围仅限于class animal。

由此可以推论,当多态的指针交给函数的时候,多态的范围就是函数;当多态的指针交给类成员的时候,多态的范围就是这个类;当多态的指针交给全局变量的时候,多态的范围就是全局;当多态的指针交给各个分散的代码段的时候,多态的范围就是各个分散的代码段。

作为一个实际例子,可以参看一下STL关于iostream的实现。在iostream类库中,filebuf作为stream_buf的派生类,通过重载为stream_buf填充和刷新buf的内容,供stream_buf使用。而含有多态内容的stream_buf指针,作为iostream类的构造函数参数,传递给iostream类,从而把多态的范围控制在iostream类。指针实际记录在basic_ios的_M_streambuf变量中。

class basic_ios: ios_base {
protected:
	char_type _M_fill;
	bool _M_fill_init;
	basic_streambuf *_M_streambuf;
	...	
public:
	bool operator!();
	void _M_cache_locale(locale &__loc);
	...
};

class basic_istream: basic_ios {
protected:
	streamsize  _M_gcount;
public:
	explicit
	basic_istream(__streambuf_type* __sb): _M_gcount(streamsize(0))
	{ this->init(__sb); }
	virtual ~basic_istream() { _M_gcount = streamsize(0); }
public:
	__istream_type &operator>>(__ios_type &(*__pf)(__ios_type &));
	__istream_type &operator>>(ios_base &(*__pf)(ios_base &));
	__istream_type &operator>>(short &__n);
	__istream_type &operator>>(unsigned short &__n);
	__istream_type &operator>>(int &__n);
	__istream_type &operator>>(unsigned int &__n);
	__istream_type &operator>>(long &__n);
	__istream_type &operator>>(unsigned long &__n);
	__istream_type &operator>>(long long &__n);
	__istream_type &operator>>(unsigned long long &__n);
	__istream_type &operator>>(float &__f);
	__istream_type &operator>>(double &__f);
	__istream_type &operator>>(long double &__f);
	__istream_type &operator>>(void *&__p);
	__istream_type &ignore(streamsize __n);
	__istream_type &ignore(streamsize __n, int_type __delim);
};

这里展示的istream作了大量的简化,无关部分已经省略。详细请看编译器的STL源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值