现在的位置: 首页 > 综合 > 正文

Loki库:多继承的改良

2013年10月13日 ⁄ 综合 ⁄ 共 4675字 ⁄ 字号 评论关闭
 


 



Loki库:多继承的改良

 



多继承,总是被我和
goto联系在一起。从逻辑上,它们都是语言的必须组成部分,但在理论上被证明可以完全不使用它们。已经形式了这样的“圣条”:尽可能不要使用它们。并且甚至已被曲解为“绝对不要使用它们”。


Steve
Maguire的《开发过程调试技术》中指出了可以安全使用goto的地方。而在Loki库中也指出了多继承的安全使用。


几乎只有C++支持多重继承,不是多余,而是因为没有支持“interface”。OO中讲应该对接口进行编程,而C++作为严格的编译期类型检查语言,将它曲解为“对类型进行编程”了。于是需要依靠多继承和模板来补救这种缺陷。



多继承会发生问题主要是“菱形缺陷”,以及“
this指针的值跳变”。


this指针的值跳变”主要对“对象同一性”判断制造了障眼法。可参看《Exceptional
C++Item 38C++只规定相同地址指向的一定是同一对象,而地址不同的并不说明任何问题,所以,使用地址进行“同一性”判断本来就是错误行为(只是绝大部分情况下是可用的),多继承不该对此承担骂名。



用“虚基类”来解决“菱形缺陷”则是使问题更加复杂化了。首先应该还“继承”以本来面目:继承不是为了得到实现,而是为了得到接口。所以,《
More
Effective C++Item 33讲,“
将非尾端类设计为抽象类”。但这些非尾端的抽象类一般来说是准实体类。要想安全地使用多继承,只能有最多一个基类是准实体类,其它基类必须是纯接口类。这些纯接口类,在《Modern
C++ Design
》中被限定为主要扮演“策略类”的角色,并叫之为“基于策略编程”。关于“基于策略编程”,由于可以下载到原书17两章,及《极限编程研究》上还有一篇论文,所以我就不多谈了。



Loki
库中的多继承是依靠TypeList,用二重继承递归实现的,在下面的visitor源码中会看得很清楚。第一反应就是:非常象设计模式中的“外观模式”。实际使用上来说,当然差很远的。我对其使用卡壳了很久,直到现在为止,仍然不能贯通起来,看来只能等书出来了再研究了。想来大家都会对这种用法比较震惊,所有我将在下一篇贴出的HierarchyGenerators.h的源码注解,以供大家集思广益了。



以随感一中讲的
visitor模式源码为例,讲解随感二中留下的“精确向下类型映射”:



////////////////////////////////////////////////////////////////////////////////



// class template BaseVisitor



// The base class of any Acyclic Visitor



////////////////////////////////////////////////////////////////////////////////



 



   


class BaseVisitor



   


{



   


public:



       


virtual ~BaseVisitor() {} //WQ
注:没有visit方法,所有隔绝循环依赖。



   


};


   



////////////////////////////////////////////////////////////////////////////////



// class template Visitor



// The building block of Acyclic Visitor



////////////////////////////////////////////////////////////////////////////////



 



   


template <class T, typename R = void>



   


class Visitor



   


{



   


public:



       


typedef R ReturnType;



       


virtual ReturnType Visit(T&) = 0; //WQ
注:这个函数看似不起眼,却很关键



                                         


//
如果画出继承图,并将它放进去的话,就



        
                                 
//
看得很清楚了。



   


};


   



////////////////////////////////////////////////////////////////////////////////



// class template Visitor (specialization)



// This specialization is not present in the book. It makes it
easier to define



// Visitors for multiple types in a shot by using a typelist.
Example:



//       
//WQ
注:这是典型运用,请多体会。



// class SomeVisitor :



//     public BaseVisitor
// required



//     public
Visitor<TYPELIST_2(RasterBitmap, Paragraph)>,



//     public
Visitor<Paragraph>



// {



// public:



//     void
Visit(RasterBitmap&); // visit a RasterBitmap



//     void
Visit(Paragraph &);   // visit a
Paragraph



// };



////////////////////////////////////////////////////////////////////////////////



   


//WQ
注:是前面visitor的偏特化。它自己可独立形成循环依赖的visitor模式。



   


template <class Head, class Tail, typename R>



   


class Visitor<Typelist<Head, Tail>, R>



       


: public Visitor<Head, R>, public Visitor<Tail, R>



   


{               
//WQ
注,本想画出递归继承图的,vision图太麻烦了,请自己画吧。



   


public:



       


typedef R ReturnType;



      


// using Visitor<Head, R>::Visit;  //WQ
注:无需using,因为所有的visit方法都



      


// using Visitor<Tail, R>::Visit;  //
都是纯虚函数,必然要在最终类真正实现的



   


};



   


//WQ
这是递归的结束点。



   


template <class Head, typename R>



   


class Visitor<Typelist<Head, NullType>, R> : public
Visitor<Head, R>



   


{



   


public:



       


typedef R ReturnType;



       


using Visitor<Head, R>::Visit;



   


};



 



////////////////////////////////////////////////////////////////////////////////



// class template BaseVisitorImpl



// Implements non-strict visitation (you can implement only part
of the Visit



//     functions)



////////////////////////////////////////////////////////////////////////////////



   


//WQ
注:这是另外一种带默认实现的visitor版本。



   


template <class TList, typename R = void> class BaseVisitorImpl;



 



   


template <class Head, class Tail, typename R>



   


class BaseVisitorImpl<Typelist<Head, Tail>, R>



       


: public Visitor<Head, R>



       


, public BaseVisitorImpl<Tail, R>



   


{           
//WQ
注,本想画出递归继承图的,vision图太麻烦了,请自己画吧。



   


public:



      


// using BaseVisitorImpl<Tail, R>::Visit;



 



       


virtual R Visit(Head&)  //WQ
注:是对visitor<Head,R>visit方法的override



       


{ return R(); }        
//WQ
注:R()void都成立!



   


};


   



   


template <class Head, typename R>



   


class BaseVisitorImpl<Typelist<Head, NullType>, R>



       


: public Visitor<Head, R>



   


{



   


public:



       


virtual R Visit(Head&)



       


{ return R(); }



   


};


   



//WQ
注:如前典型用法所示,最终的visitor实体类从BaseVisitorVisiotr<TypeList>//重继承。如果TypeList中的多个类型间有继承关系,由于其实际基类是Visitor<T>,继承//关系被隔绝,不存在“菱形缺陷”。



 



////////////////////////////////////////////////////////////////////////////////



// class template BaseVisitable



////////////////////////////////////////////////////////////////////////////////



 



template <typename R, typename Visited>



struct DefaultCatchAll



{



   


static R OnUnknownVisitor(Visited&, BaseVisitor&)



   


{ return R(); }



};



 



////////////////////////////////////////////////////////////////////////////////



// class template BaseVisitable



////////////////////////////////////////////////////////////////////////////////



 



   


template     



   


<



       


typename R = void,



       


template <typename, class> class CatchAll = DefaultCatchAll



   


>



   


class BaseVisitable



   


{



   


public:



       


typedef R ReturnType;

抱歉!评论已关闭.