Note of Justin

关于工作和读书的笔记

  C++博客 :: 首页 :: 联系 :: 聚合  :: 管理
  47 Posts :: 0 Stories :: 45 Comments :: 0 Trackbacks

留言簿(14)

搜索

  •  

积分与排名

  • 积分 - 51844
  • 排名 - 433

最新评论

阅读排行榜

评论排行榜

[原创文章欢迎转载,但请保留作者信息]
Justin 于 2010-01-24

前面已经学过,用虚函数来实现接口是再自然不过的事情。这里要说的是,除了直接单纯使用虚函数机制,还有一些别的方法。

大师说的第一种,是模板模式,利用非虚拟接口函数(Non-Virtual Interface, NVI)来实现。此模板(设计模式中的模板方法,template method)非彼模板(C++中的模板,template),而且也没那么难:

在父类中提供一个公有函数(接口),然后在其中调用真正干活的私有虚函数(默认实现);子类对象通过公有继承自然得到了这个函数(接口),如果子类没有编写自己的实现版本,最终执行的就是默认的实现;如果子类实现了自己的版本,调用的就是子类的版本。(是不是和上节课的1.5有点亲戚关系?)

class  AClass
{
   
public :
      
void   interface ()
      
{
         printf(
" in base::interface()\n " );
         do_interface();
      }

   
private :
      
// the default implementation
       virtual   void  do_interface()
      
{
         printf(
" in AClass::do_interface()\n " );
      }

}
;

class  AClassDerived :  public  AClass
{
   
private :
/*  derived can has its own implementation, but not a must..
      virtual void do_interface()
      {
         printf("in AClassDerived::do_interface()\n");
      }
*/

}
;
【给自己的】如果看到这里还会想:为什么是私有的虚函数?就搜“与大虾对话:领悟设计模式”复习复习……

看了第一种方法的大多数同学都会有这种想法:这不还是要用虚函数么?穿个wrapper的马甲就认不出你了?大师马上说
第二个替代产品是策略模板(strategy pattern),利用函数指针实现:

这种方法的实质,就是把接口函数的实现拿到了类之外。类之中只声明接口的形式,只定义一个函数指针。真正干活的函数(实现)都不是类的成员。
这样做带来了一定的灵活性,具体采用哪种实现与类的继承关系是独立无关联的;同时,非类成员函数也有局限性:无法访问类的非公有成员。如果把函数定义为友元或利用公有函数输出私有成员,又会破坏原设计的
封装。如下代码所示:

class  AClass
{
   
public :
      typedef 
void   * (Interface)( /* param.. */ );
      
explicit  AClass( Interface pint  =  defaultInterface) : pInterface(pint)
      
{}
      
// ..
    private :
      Interface pInterface;
// ..
}
;

在构造AClass对象的时候即可指定Interface的真身,虽然,它无法直接访问AClass的非公有成员。

估计大师也觉得指针在C++里简单一些,于是更推崇用C++的库(如TR1中的function)来管理接口函数。

原理和函数指针是一样的,只不过因为用了对象来管理资源,使得应用更加灵活。当然,要付出更多一点的代码体积和运行时间代价。

class  AClass
{
//  all are the same with the funtion pointer version
//  except for:
   typedef std::tr1::function void  ( /* param.. */ ) >  Interface;
// ..
}
;

大师在最后才说出了最经典的策略模式实现,也是我觉得比较漂亮且容易理解的实现方式。

用两个类搞定:

class  AInterface
{
   
public :
      
// .. 
       virtual   void  DoInterface( /*  param..  */ );
   
// .. 
};

AInterface defaultInterface;

class  AClass
{
   
public :
      
explicit  AClass(AInterface  *  pinter  =   & defaultInterface) : pInter(pinter)
      {} 
      
void  TryInterface()
      {
         pInter
-> DoInterface();
      }
   
// .. 
    private :
      pInterface 
*  pInter;
   
// .. 
};

看到最后,似乎本课的思想就是用模式设计(template pattern或strategy pattern)来代替简单的虚函数设计。
但是,大师临走前又说了:以上只是举例,为的是说明其实除了简单的虚函数外,还有很多种可能的方式来替代它完成设计需要。

posted on 2010-02-25 23:41 Justin.H 阅读(501) 评论(0)  编辑 收藏 引用 所属分类: Effective C++ 炒冷饭

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理