一种构件的继承方法

文档序号:6555699阅读:199来源:国知局
专利名称:一种构件的继承方法
技术领域
本发明涉及一种构件的继承方法,尤其是一种同时具有封装性和多态性的构件继承方法。

背景技术
在现有的面向对象的高级语言中如C++语言,面向对象程序设计的机制如有类、对象、派生与继承、模板、虚函数等等。类的派生和继承是经常会被使用,在类的派生和继承中,已存在的用来派生新类的类为基类,又称为父类;由已存在的类派生出的新类为派生类,又称为子类。C++的虚函数实现了面向对象的运行时多态性,允许派生类取代基类所提供的实现。派生的新类将继承其父类的操作和数据结构,运行时,在基类里调用虚函数,会跳到其派生类的方法中执行;派生类可以重载和调用其父类的虚函数。通过算柱状体体积,举例说明现有的C++语言中的类继承机制假设类Volume用于求横截面是任意形状的柱状体体积的抽象类。定义及实现代码如下 class Volume{publicvirtual double CalcArea()=0;//计算横截面面积(纯虚函数)double CalcVolume(); //计算柱状体体积double m_dfHigh; //柱状体高度};double VolumeCalcVolume(){return CalcArea()*m_dfHigh;//体积=面积*高度} 从类Volume中派生出两个类圆柱体类Column;横截面是正方形的长方体类Cuboid。定义及实现代码如下   nCalcArea()  {  //圆面积=PI*半径*半径<!-- SIPO <DP n="1"> --><dp n="d1"/>  return 3.1415926*m_dfRadius *m_dfRadius;}class Cuboidpublic Volume{public  double CalcArea(); //重载计算横截面面积的虚函数  double m_dfside; //横截面边长};double CuboidCalcArea(){  return m_dfside*m_dfside ; //正方形面积=边长*边长} 使用以上C++类的客户端程序 int main(){Column columnObj;//圆柱体对象columnObj.m_dfRadius=3; //横截面半径为3columnObj.m_dfHigh=10; //圆柱体高度为10//计算并打印圆柱体体积printf(″Column volume%g\n″,columnObj.CalcVolume());Cuboid cuboidObj;//横截面的正方形的长方体对象cuboidObj.m_dfside=5; //横截面边长为5cuboidObj.m_dfHigh=8; //长方体高度为8//计算并打印长方体体积printf(″Cuboid volume%g\n″,cuboidObj.CalcVolume());return 0;} 运行结果是 Column volume282.743 Cuboid volume200 也就是说,求圆柱体体积时调用的是类Column重载的CalcArea()函数,而求长方体体积时调用的是类Cuboid重载的CalcArea()函数。即CalcArea()函数即能指向类Column的实例,又能指向类Cuboid的实例,这就是C++虚函数的多态性。但是,从上述也可以看出C++的虚函数技术是基于C++类的源代码级别的继承与重载机制,必须暴露基类的数据结构,违反了封装性。
除了上述C++语言中的类继承之外,现有还有两种构件继承方法,一种为包容技术,另一种为聚合技术。构件是指对外提供一组规约化接口的,符合一定标准的、可替换的软件系统得程序模块。
下面通过算柱状体体积的构件为例讲述如何复用该构件。例子中CVolume是一个用于求任意横截面的柱状体体积的构件。它的算体积接口需要知道横截面的面积,而外部构件(如圆柱体构件)会实现一个算横截面面积的接口。
如图1为包容技术复用构件算柱状体体积的结构图,外部构件如圆柱体构件(CColumn)包含指向内部构件(CVolume)接口的指针。此时外部构件仅仅是内部构件的一个客户而已,它将使用内部构件的算体积接口来实现它自己的算体积接口。
外部构件也可以通过将下述调用过程,转发给内部构件的算体积方法来重新实现内部构件所支持的算体积接口。并且外部构件还可以在内部构件代码的前后加上一些代码以对接口进行改造。
算圆柱体体积的调用过程如下A创建CColumn构件类的实例,在创建过程中会创建CVolume构件类的实例并保存其接口指针;B用户调用CColumn的算体积接口,在CColumn构件类的实现中调用算横截面面积接口实现的算横截面面积方法;C把得到的横截面面积作为参数传入CVolume构件类的设置横截面面积接口;D最后调用CVolume构件类的算体积接口得到结果并返回。但是这种上述的这种算体积构建复用存在以下的缺点本来应该复用CVolume构件类的算体积接口,结果需要CColumn构件类相应地先实现一个算体积接口,并把横截面面积参数传给CVolume构件类的设置横截面面积接口方法中。因为CVolume构件无法直接调用CColumn的算横截面积接口,CVolume构件需要一个辅助的接口设置横截面积接口。也即,在使用这种包容技术时,存在着需要外部构件将本该复用的接口,相应先实现,且内部构件需要设置辅助接口的缺点。
聚合是包容的一种变化形式。当外部构件聚合了某个内部构件的一个接口时,它并没有像包容那样重新实现此接口并显式地将调用请求转发给内部构件。相反,外部构件直接把内部构件的接口指针返回给客户。使用这种方法,外部构件将无需重新实现并转发接口中的所有函数。但使用这种方式,外部构件将无法对接口中的函数进行任何改造。当外部构件将内部构件的接口返回给客户之后,客户就可以直接同内部构件打交道了。
图2为聚合技术复用构件算柱状体体积的结构图,具体的调用过程如下a创建CColumn构件类的实例,在创建过程中会创建CVolume构件类的实例,并通过保存各自的IUnknown接口指针把两个构件聚合在一起,使其从外界看来是一个大构件;b调用CCloumn实例的算横截面面积接口得到圆柱的横截面面积;c调用CVolume实例的设置横截面面积接口;d调用CVolume的算体积接口得到体积。
上述的这种算体积所采用的聚合方法,存在着由于CVolume构件无法直接调用CColumn的算横截面积接口,CVolume构件需要设置一个辅助接口设置横截面积接口。因此,聚合技术存在着以下的缺点内部构件的接口完全暴露给用户,外部构件无法对内部构件的接口进行改造;并且内部构件需要设置辅助接口。
下面介绍本发明所涉及的CAR构件,CAR即Component ApplicationRuntime,是一种构件技术。CAR构件技术是面向构件编程的编程模型,它规定了一组构件间相互调用的标准,使得二进制构件能够自描述,能够在运行时动态链接。
CAR与微软的COM类似,但是和微软COM相比,CAR删除了COM中过时的约定,禁止用户定义COM的非自描述接口;完备了构件及其接口的自描述功能,实现了对COM的扩展;对COM的用户界面进行了简化包装,易学易用。
从上面的定义中,我们可以说CAR是微软COM的一个子集,同时又对微软的COM进行了扩展,在SDK工具的支持下,使得高深难懂的构件编程技术很容易被C/C++程序员理解并掌握。


发明内容
本发明的目的是为了克服现由技术的缺陷,提供一种具有多态性、封装性、多层继承和多重继承的构建继承方法,实现在构件类继承时,即使基构件类内部代码变动,对继承其的派生类影响很小。
为实现上述目的,本发明提供了一种构件的继承方法。该方法包括 步骤1,创建基构件类和第一派生构件类的实例; 步骤2,所述基构件类和第一派生构件类的实例中分别获取并保存对方的虚接口指针; 步骤3,调用所述基构件类的第一辅助接口; 步骤4,根据所述基构件实例保存的虚接口指针,调用所述第一派生构件的虚接口,实现第一辅助接口。
由以上技术方案可知,当基构件类(基类)的一个接口是“虚接口”即在CAR构件的接口定义中有virtual属性时,其派生构件类将可以覆盖该“虚接口”的所有方法,实现了构件级别的多态性。基类是一个构件,具有构件的特性,包括封装性。基类不须暴露其内部结构。基类只要接口不变,无论怎样升级更新或改变内部结构,派生类都不需要重新编译。
下面通过具体实施例并结合附图对本发明做进一步的详细描述。



图1为现有技术包容技术复用构件算柱状体体积的结构图; 图2为现有技术聚合技术复用构件算柱状体体积的结构图; 图3为本发明构件继承方法具体实施例1的结构示意图; 图4为本发明构件继承方法具体实施例1的流程图; 图5为本发明构件继承方法的实施例2的结构示意图; 图6为本发明构件继承方法的实施例2的流程图; 图7为本发明构件继承方法的实施例3的结构示意图。

具体实施例方式 本发明提供的这种构件继承方法,不仅具有多态性还具有多层性。外部构件即派生构件能够重载内部构件即基构件的虚接口,即基构件的虚接口能够被它的派生构件重载,虚接口的方法能够指向不同的派生构件的实例,因此在这种构件继承方法中具有多态性。如图3所示的本发明构件继承方法具体实施例1的结构示意图,在本实施例中,基构件类为CVolume用于求任意横截面的柱状体体积的构件,现需要根据该基构件类计算圆柱体体积,构建一圆柱体构件类CColumn构件类,该圆柱体构件类继承CVolume构件类。
  volume.car文件[  uuid(7677c5cf-9d3e-4d1f-bcfe-9e70feb62e5b),  uunm(www.koretide.com/ezcom/volume.dll)]component VolumeComponent{   [uuid(27ae16a8-3f9f-4c5b-b33f-1be1cb2f3655)]   interface ICrosssection{   HRESULT CalcArea([out]double*pdfArea);   }   [uuid(7b03e076-3bd2-4231-b2a4-75644179836e)]   interface IVolume{   HRESULT SetHigh([in]double dfHigh);   HRESULT CalcVolume([out]double*pdfVolume);   }   [uuid(07060acb-3026-4150-b770-7b34bd217264)]   class CVolume{   public//下面定义的接口是public接口,可被继承   virtual interface ICrosssection;//虚接口   interface IVolume; //一般接口   }} 其中“public”可以省略,表示在public作用域的接口可被继承。类似的还有protected、private等关键字。在protected作用域里定义的接口可被继承,但不能被构件类的实例调用。而在private作用域里定义的接口不能被继承,也不能被构件类的实例调用。通常protected、private关键字修饰的接口是为实现该构件类而定义的一些辅助接口。
virtual关键字表示该接口为“虚接口”,与C++语言中的虚函数对应,虚接口中的接口方法可被派生构件重载,并且可以从基类中调用到重载后的派生类接口实现。在本范例的抽象构件类CVolume中柱状体体积的实现,是调用虚接口ICrossSection中的CalcArea()得到横截面面积,再乘以高度计算出来的。其中CalcArea()会跳到相应派生类所重载的CalcArea()中执行。
  CVolume类的关键实现代码……HRESULT CVolumeCalcArea(   /*[out]*/double * pdfArea){   return E_NOTIMPL;//本基类不实现计算面积的方法,由派生类重载<br/>}HRESULT CVolumeCalcVolume(   /*[out]*/double * pdfVolume){   if(pdfVolume){   double dfArea;   //调用虚ICrossSection接口中的CalcArea()方法计算面积   //将会跳到派生类重载的CalcArea()方法执行   MyVirtualICrossSection().CalcArea(&amp;dfArea);   //柱状体体积=横截面面积*高度   *pdfVolume=dfArea * m_dfHigh;   return S_OK;   }   return S_FALSE;  } MyVirtualICrossSection()函数是CAR自动代码生成工具实现的,函数返回ICrossSection虚接口的智能指针。
MyVirtualICrossSection().CalcArea(&dfArea)表示调用虚接口中的CalcArea()方法,而不是在本CVolume类CalcArea()方法。上述代码表示了调用虚接口中的方法将会跳到派生类重载的该方法中去执行。
   派生类圆柱体的构件描述文件column.car[   uuid(272eb044-0e9a-45db-a158-3a4cf60ddcb3),   uunm(www.koretide.com/ezcom/column.dll)]component ColumnComponent{   importlib(″volume.dll″);//导入基类的元数据   [uuid(0c608066-fdoc-4ad8-a2c0-149e7cbaf1a6)]   interface IColumn{   HRESULT SetRadius([in]double dfRadius);   }   [uuid(4f145e76-80c1-4239-bb78-b1ec54211c57)]   class CColumnCVolume{//继承CVolume类   interface IColumn;   }} 其中“importlib(“volume.dll”)”是为了导入基类的元数据信息,包括ICrossSection、IVolume接口和CVolume类的定义。
后面的“class CColumnCVolume”表示CColumn类继承CVolume类。这样,CColumn类就自然具有了ICrossSection和IVolume两个public接口的定义与实现了(默认调用基类相应接口的实现)。但是,基类的CalcArea()方法是未实现的(return E_NOTIMPL),需要重载。
  CColumn.cpp的关键实现代码如下……//重载calcArea()方法HRESULT CColumnCalcArea(   /*[out]*/double*pdfArea){   if(pdfArea){  //圆的面积=PI*半径*半径   *pdfArea=3.1415926*m_dfRadius*m_dfRadius;   return S_OK;  }  return S_FALSE;} 在构建上述代码之后,在主程序main()控制下,如图4所示的流程图,执行以下步骤 步骤1创建CColumn构件类即第一派生构件类和CVolume类即基构件类的实例; 步骤2CColumn派生构件类和CVolume基构件类实例各自保存另一方的虚接口即算横截面面积接口的指针;具体代码实现如上述MyVirtualICrossSection().CalcArea();该函数在CColumn派生构件类和CVolume基构件类实例的创建过程中返回智能指针后,CColumn派生构件类实例和CVolume基构件类实例分别将对方的虚接口ICrossSection接口中算横截面面积方法CalcArea()指针保存;其中具体为该CColumn派生构件类调用CVolume的IVirtualInheritHelper接口的SetMyVirtualInterfacePtr()函数将CColumn派生构件类的虚接口指针传递给CVolume基构件类,该虚接口即为CColumn所实现的ICrossSecsion接口,在实例化CVolume基构件类和CColumn派生构件类时,创建CColumn派生类之后,派生类在创建CVolume基构件类对象时,在内存中,设置m_virtualICrossSection和m_parentICrossSection接口指针,m_virtualICrossSection指针指向所实例化的CColumn构件类的ICrossSection接口,m_parentICrossSection接口指针指向实例化的CColumn构件类的ICrossSection接口,CColumn派生类调用MyVirtualICrossSection()函数,该函数是CAR自动代码生成工具实现的,函数返回ICrossSection虚接口的智能指针。
步骤3调用CVolume基构件类的算体积接口即IVolume第一辅助接口;具体代码如描述文件column.car中class CColumnCVolume{//继承CVolume类;interface IColumn所示; 步骤4CVolume构件类实例根据保存的CColumn构件类的虚接口的指针,即算横截面面积接口指针,调用CColumn构件类的算横截面面积接口,具体代码如CColumn.cpp段代码所示,实现算体积接口。
其中调用CColumn构件类的算横截面面积接口,实现圆的横截面面积,具体为CColumn派生构件类实例中,算横截面面积接口重载CVolume基构件类的虚接口中的方法。并且,在方法的参数和返回值类型必须与基类定义的一样。
其中,基构件类可以有多个虚接口以及第一辅助接口。派生构件类可以重载多个虚接口,并且继承基构件类中多个第一辅助接口。
如图5为本发明构件继承方法的实施例2结构示意图,在本实施例中,构件继承可以做到多层继承。在这实现一个横截面为半圆的柱状体的构件类。半圆柱体构件类继承圆柱体构件类,其横截面面积是后者的一半。以下是该类的构件描述文件halfcolumn.car [   uuid(a464fadf-9f54-46bb-8e2d-798dobb239c6),   uunm(www.koretide.com/ezcom/halfcolumn.dll)]component HalfColumnComponent{  importlib(″volume.dll″);//导入基类的元数据  importlib(″column.dll″);//导入基类的元数据  [uuid(24b74b7d-76af-46bf-ad37-8fb73cffd78b)]  class CHalfColumnCColumn {//继承CColumn类  }} 这里,CHalfColumn第二派生类继承自CColumn第一派生类,而CColumn第一派生类继承自Volume基构件类。也就是说,CAR构件继承机制做到了多层继承。
   CHalfColumn.cpp的关键实现代码如下……//重载CalcArea方法HRESULT CHalfColumnCalcArea(   /*[out]*/double*pdfArea){   if(pdfArea){   double dfArea;   //获得父类CColumn横截面面积(圆的面积)   MyParentICrossSection().CalcArea(&amp;dfArea);   //半圆面积=圆的面积/2<!-- SIPO <DP n="10"> --><dp n="d10"/>   *pdfArea=drArea/2;   return S_OK;  }  return S_FALSE;} 半圆柱体构件类重载的CalcArea()方法的实现是,先计算父类CColumn的横截面面积再除以2。要获得父类的横截面面积,可以先调用MyParentICrossSection()函数获得父类所实现的ICrossSection接口的智能指针,再执行其CalcArea()方法。其中MyParentICrossSection()函数是自动代码生成工具根据构件元数据所生成的代码实现的,作用是返回父类所实现的ICrossSection接口的智能指针。命名规则是在接口名前拼上MyParent,表示父类所实现的相应接口。所有从父类继承下来的public或protected关键字修饰的接口都有与之对应的MyParent函数,方便在重载或实现其它接口方法时调用父类的接口方法实现。
在构建上述代码之后,在主程序main()控制下,如图6所示的实施例2的流程图,在上述步骤4之后,还可包括以下步骤 步骤5,创建CHalfColumn第二派生构件类的实例同时创建CColumn第一派生构件类和CVolume基构件类的实例; 步骤6CHalfColumn第二派生构件类的虚接口即算横截面面积接口指针保存到CColumn第一派生构件类和CVolume基构件类中;第二派生构件类调用第一派生构件类的IVirtualInheritHelper接口的SetMyVirtualInterfacePtr()函数,将所述第二派生构件类的虚接口指针传递给第一派生构件类;第一派生构件类调用基构件类的IVirtualInheritHelper接口的初始化接口方法SetMyVirtualInterfacePtr()函数,将第二派生构件类的虚接口指针传递给所述基构件类;设置好各对象的m_virtualICrossSection和m_parentICrossSection接口指针,其中所有m_virtualICrossSection指针指向所实例化的构件类CHalfColumn类的ICrossSection接口,MyVirtualICrossSection()函数返回的该指针,另一方面,m_parentICrossSection指针指向父类的ICrossSection接口,以便重载时根据需要调用父类所实现的接口。MyParentICrossSection()函数返回该指针; 步骤7调用CVolume基构件类的算体积接口即第一辅助接口; 步骤8根据基构件实例保存的虚接口指针,调用第二派生构件类CHalfColumn的虚接口即算横截面面积接口,实现CVolume基构件类的算体积接口。
在调用第二派生构件类CHalfColumn的虚接口即算横截面面积接口计算半圆横截面实现中,调用CColumn第一派生构件的算横截面面积虚接口进行计算,并把得到的结果除以2。
CHalfColumn类继承自CColumn类,而CColumn类继承自Volume类。也就是说,CAR构件继承机制做到了多层继承。
由于基类CVolume没有父类,所以没有m_parentICrossSection变量,也就不需要设置了。对于另一个变量m_virtualICrossSection,该指针变量指向最外层类对象的ICrossSection接口。
基于上述基础,本发明构件继承还能做到多重层继承。例如横截面是半圆加上一个三角形的柱状体体积如图7实施例3所示结构示意图,具体过程为创建CTriangleHalfColumn构件类的实例,在创建过程中会创建CHalfColumn、CColumn和CVolume类的实例。并且把CTriangleHalfColumn类的算横截面面积接口指针保存到CHalfColumn、CColumn和CVolume类中。客户调用CVolume的算体积接口;CVolume的算体积接口实现里调用外部构件CTriangleHalfColumn的算横截面面积接口,在第一步时保存了CTriangleHalfColumn的接口指针;CTriangleHalfColumn的算横截面面积的实现中会调用CHalfColumn和Ctriangle类的算横截面面积,并把得到的结果相加;得到CtriangleHalfColumn类的横截面面积后,利用结果计算出体积并返回。
本发明提供了一种具有多态性、封装性、多层继承和多重继承的构建继承方法。
最后所应说明的是,以上实施例仅用以说明本发明的技术方案而非限制,尽管参照较佳实施例对本发明进行了详细说明,本领域的普通技术人员应当理解,可以对本发明的技术方案进行修改或者等同替换,而不脱离本发明技术方案的精神和范围。
权利要求
1、一种构件的继承方法,其特征在于,包括以下步骤
步骤1,创建基构件类和第一派生构件类的实例;
步骤2,所述基构件类和第一派生构件类的实例中分别获取并保存对方的虚接口指针;
步骤3,调用所述基构件类的第一辅助接口;
步骤4,根据所述基构件实例保存的虚接口指针,调用所述第一派生构件的虚接口,实现第一辅助接口。
2、根据权利要求1所述的方法,其特征在于,所述步骤1中创建第一派生构件类的实例具体包括所述第一派生构件类继承所述基构件类的元数据,以及继承所述基构件类中接口的方法。
3、根据权利要求1所述的方法,其特征在于,所述步骤2中获取对方的虚接口指针具体为所述第一派生构件类调用基构件类的初始化接口方法,将所述第一派生构件类的虚接口指针传递给所述基构件类。
4、根据权利要求1所述的方法,其特征在于,所述步骤4中调用第一派生构件的虚接口的实现具体为所述第一派生构件的虚接口重载所述基构件类的虚接口中的方法。
5、根据权利要求1所述的方法,其特征在于,所述步骤5之后还包括以下步骤
步骤5,创建第二派生构件、所述基构件和第一派生构件的实例;
步骤6,保存所述第二派生构件的虚接口的指针到所述基构件和第一派生构件中;
步骤7,调用基构件类的第一辅助接口;
步骤8,根据基构件实例保存的虚接口指针,调用所述第二派生构件的虚接口,实现基构件类的第一辅助接口。
6、根据权利要求1所述的方法,其特征在于,所述步骤1中创建第一派生构件类的实例具体包括所述第一派生构件类继承所述基构件类的元数据,以及继承所述基构件类中接口的方法。
7、根据权利要求5所述的方法,其特征在于,所述步骤8中的调用第二派生构件的虚接口的实现具体为调用第一派生构件的虚接口。
8、根据权利要求5所述的方法,其特征在于,所述步骤6具体为所述第二派生构件类调用第一派生构件类的初始化接口方法,将所述第二派生构件类的虚接口指针传递给所述第一派生构件类;所述第一派生构件类调用基构件类的初始化接口方法,将所述第二派生构件类的虚接口指针传递给所述基构件类。
全文摘要
本发明涉及一种构件的继承方法,包括以下步骤创建基构件类和第一派生构件类的实例;所述基构件类和第一派生构件类的实例中分别获取并保存对方的虚接口指针;调用所述基构件类的第一辅助接口;根据所述基构件实例保存的虚接口指针,调用所述第一派生构件的虚接口,实现第一辅助接口。本发明实现了构件级别的多态性、封装性、多层继承和多重继承的构建继承方法,实现在构件类继承时,即使基构件类内部代码变动,对继承其的派生类影响很小。
文档编号G06F9/44GK1908896SQ200610030370
公开日2007年2月7日 申请日期2006年8月24日 优先权日2006年8月24日
发明者梁宇洲, 陈永生, 黄凯峰, 苏翼鹏, 陈榕 申请人:上海科泰世纪科技有限公司
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1