纯虚函数的默认实现
来源:互联网 发布:单片机延时1s程序汇编 编辑:程序博客网 时间:2024/06/06 12:51
纯虚函数的默认实现
分类: C++ 设计与模式2011-11-16 22:40 1720人阅读 评论(5) 收藏 举报
class审查工作
在帮新同事进行代码审查的时候,常常会发现这样的问题:代码中原有基类B和派生类D1,现在新加一个派生类D2,它有一个函数f2()。由于经验不足,新同事并没有注意到D1也有类似的函数f1()。于是造成了类似的代码出现在了两个地方,代码冗余造成将来的维护工作异常困难。注意到f()实际上是一个通用的行为,我们可以把它抽出来放到基类中,如下所示。注意,这个问题的本质并不是说基类不能有缺省的实现,而是说如果派生类需要使用基类缺省的实现,必须显式地表示出来。所以,我们需要一个能够强制派生类定义f的方式,答案就是纯虚函数。
我们知道有纯虚函数的类是抽象类,而抽象类是无法实例化的。如果D3没有实现f,那么D3也无法实例化。这就要求每个要实例化的子类都必须显示地实现纯虚函数f。另一方面,f的缺省实现放哪里?
一种方法是把缺省实现作为另一个非虚函数放在基类里,当然它是保护的,这样外界无妨直接访问而派生类可以通过调用该函数来达到缺省的行为。
第二种方法是把缺省的实现放入基类纯虚函数的函数体。没错,纯虚函数可以有函数定义存在,它的作用就是提供虚函数缺省的实现方式。和一般虚函数不同,派生类必须重新定义纯虚函数。如果需要使用缺省实现,也必须显式地调用基类的相关函数。
这种方法的好处是少了一个需要维护的函数,缺点是客户代码可以直接调用基类的缺省实现。
- class B
- {
- public:
- virtual void f();
- };
- void B::f()
- {
- //f默认的实现方式..
- }
- class D1: public B {...};
- class D2: public B {...};
这里有两点。基类里面的f()有函数定义是为了避免代码冗余,因为D1和D2关于f的实现都是相同的。f()是虚函数是考虑到将来万一有一个派生类需要f()有不同的实现方式时,它可以重新定义f。
到目前为止一切顺利。好了,假设现在另一个同事又加了一个派生类D3,它要求f()有不同的实现方式。但是,他忘记了重新定义f。。这是一个灾难。
- class D3: public B {...};
- B* b = new D3;
- // f做的动作不是我希望的!
- b->f();
- class B
- {
- public:
- virtual void f() = 0;
- };
- class D3: public B {...};
- B* b = new D3; // 编译报错:抽象类无法实例化
- b->f();
一种方法是把缺省实现作为另一个非虚函数放在基类里,当然它是保护的,这样外界无妨直接访问而派生类可以通过调用该函数来达到缺省的行为。
- class B
- {
- public:
- virtual void f() = 0;
- protected:
- void f_impl();
- };
- void B::f_impl()
- {
- // 缺省实现..
- }
- // D2类似
- class D1: public B
- {
- public:
- virtual void f()
- };
- void D1::f()
- {
- // 对于缺省实现已经够用的派生类来说,调用基类的缺省实现就可以了
- f_impl();
- }
- class D3: public B
- {
- public:
- virtual void f()
- };
- void D3::f()
- {
- // 特殊实现..
- }
- class B
- {
- public:
- virtual void f()
- };
- void B::f()
- {
- // 缺省实现..
- }
- // D2类似
- class D1: public B
- {
- public:
- virtual void f()
- };
- void D1::f()
- {
- // 显式调用基类的缺省实现
- B::f();
- }
- B* b = new D1;
- b->B::f();
小结:
- 普通的虚函数提供了接口与缺省实现。(公有继承的)派生类继承接口的同时可以自动继承接口的缺省实现(免费的午餐),或者选择重新定义该函数来特化自己的行为。风险是以后需要定制此行为的派生类可能因为忘记重定义而错误地使用缺省实现。
- 纯虚函数只提供了接口。但是具有函数体的纯虚函数同时还提供了缺省实现。派生类必须显式定义接口。可以通过显式调用基类函数来完成缺省行为。
- 为了完整,顺便补充一下,公有非虚函数提供了接口与强制实现。也就是说所有的派生类必须继承这个接口及其实现。
0 0
- 纯虚函数的默认实现
- 纯虚函数的默认实现
- 纯虚函数的默认实现
- 纯虚函数的默认实现
- 纯虚函数的默认实现
- 带默认实现的纯虚函数
- C++纯虚函数的实现
- 纯虚函数(继承接口),虚函数(继承接口和默认实现),非虚函数(继承接口和强制实现)
- C++纯虚函数实现
- 抽象类的继承/纯虚函数的实现
- 虚函数,纯虚函数的解释和内部实现&&虚函数表的真实样子
- 纯虚函数的作用
- 纯虚函数的识别
- 纯虚函数的调用
- 纯虚函数的调用
- C方式实现C++纯虚函数
- C++纯虚函数实现接口
- 纯虚函数虚函数的区别
- 第7周 HBase集群安装,管理
- oracle 10g数据文件的表空间简单扩展
- linux的ulimit各种限制之深入分析
- flex textinput和textarea换行符
- nginx rewrite 学习备忘
- 纯虚函数的默认实现
- Java类方法的简单使用
- ios语音图片二进制流保存
- Java troubleshooting
- ios 查看UIView的层次继承关系工具
- POJ 2891 Strange Way to Express Integers
- 致年少时的热忱
- 黑马程序员_11_String类的常用方法
- Openstack 自动化部署puppet代码管理