O op Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-21 #1 一个COM类的多个接口就相当于这个类的多个纯虚父类, 如果多个纯虚父类都声明了一个相同名称的纯虚函数, 当这个函数在子类中被实现,并被这些父类调用时, 它如何判断调用自己的是哪个父类?
T TComponent Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-21 #2 当为一个类实现一个接口时,它必须逐个实现接口的每个对象方法 因此,我觉得并非像OO中那样调用父类的方法(OO中,这种情况的调用有一定顺序)
L lczhuohuo Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-21 #3 使用指示字implement可以指定实现的是哪个接口
L langer Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-21 #4 采用方法解析语句,否则Delphi认为所有接口的同名函数采用相同的实现。 方法解析格式: function IInterface1.GetName: WideString = GetName1; function GetName1: WideString; 这样,IInterface1的GetName方法采用GetName1来实现,而没有采用方法解析 语句的IInterface2仍使用GetName的实现。
采用方法解析语句,否则Delphi认为所有接口的同名函数采用相同的实现。 方法解析格式: function IInterface1.GetName: WideString = GetName1; function GetName1: WideString; 这样,IInterface1的GetName方法采用GetName1来实现,而没有采用方法解析 语句的IInterface2仍使用GetName的实现。
O op Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-22 #5 langer果真是高手,居然如此轻而一举就破解了。 唉,delphi就是delhpi,居然有自己的一套语法来实现这个功能。 可是我还是笑不出来,因为我用的是C++Builder…… langer如果用C++Builder就好了:< 看来COM是支持不同接口的函数名重载的,而且肯定不是采用我刚才的那个变通的办法。 我想COM内部一定是采用类似下面的办法来实现的: 如果有一个COM对象,我称它为TCOMObject, IUnknown IInterface1 IInterface2 是这个COM对象的3个接口。 TCOMObject_QueryInterface TCOMObject_AddRef TCOMObject_Release TCOMObject_MyFunction1 TCOMObject_MyFunction2 是这个COM对象内部的5个函数。 那么,当IInterface1和IInterface2的第三个函数名都是MyFunction时, 一定是用下面的代码来指向不同的函数地址。 *(IUnknown+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IUnknown+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IUnknown+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface1+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IInterface1+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IInterface1+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface1+3)=(void(__stdcall*)())TCOMObject_MyFunction1; *(IInterface2+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IInterface2+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IInterface2+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface2+3)=(void(__stdcall*)())TCOMObject_MyFunction2; 然而,在实际中,用C++Builder是如何实现的呢?
langer果真是高手,居然如此轻而一举就破解了。 唉,delphi就是delhpi,居然有自己的一套语法来实现这个功能。 可是我还是笑不出来,因为我用的是C++Builder…… langer如果用C++Builder就好了:< 看来COM是支持不同接口的函数名重载的,而且肯定不是采用我刚才的那个变通的办法。 我想COM内部一定是采用类似下面的办法来实现的: 如果有一个COM对象,我称它为TCOMObject, IUnknown IInterface1 IInterface2 是这个COM对象的3个接口。 TCOMObject_QueryInterface TCOMObject_AddRef TCOMObject_Release TCOMObject_MyFunction1 TCOMObject_MyFunction2 是这个COM对象内部的5个函数。 那么,当IInterface1和IInterface2的第三个函数名都是MyFunction时, 一定是用下面的代码来指向不同的函数地址。 *(IUnknown+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IUnknown+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IUnknown+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface1+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IInterface1+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IInterface1+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface1+3)=(void(__stdcall*)())TCOMObject_MyFunction1; *(IInterface2+0)=(void(__stdcall*)())TCOMObject_QueryInterface; *(IInterface2+1)=(void(__stdcall*)())TCOMObject_AddRef; *(IInterface2+2)=(void(__stdcall*)())TCOMObject_Release; *(IInterface2+3)=(void(__stdcall*)())TCOMObject_MyFunction2; 然而,在实际中,用C++Builder是如何实现的呢?
M maming Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-22 #7 To op: 你用C++,发现与DELPHI 5 有何不同吗? 能说说吗? 我常将用C++做的东东COPY到DELPHI 5中来, 因我的对DELPHI 5较会用些。 再者,我认为DELPHI 5的OOP与C++的没什么不同。
To op: 你用C++,发现与DELPHI 5 有何不同吗? 能说说吗? 我常将用C++做的东东COPY到DELPHI 5中来, 因我的对DELPHI 5较会用些。 再者,我认为DELPHI 5的OOP与C++的没什么不同。
O op Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-22 #8 差别当然有,而且不少,其它的不说,单OOP的差别就有以下..... 1、BCB可Public/Protected/private的继承父类,而D只能Public的继承父类。 (如果只能Public的继承父类,将导致子类一定大于父类,而不能屏蔽父类的方法,这对面向对象来说是不利的。) 2、BCB可真正的写自己的类,而不用一定要从TObject来继承。 (在写一个小型的类时很方便,而且实例可以生成在栈里,而不是在堆里。) 3、BCB类与简单类型用法一致,无须特殊对待。 4、D中,一个Unit文件里不同Class的变量可共访。 (这将导致编程“语言”与物理“文件”的相关性。) 5、BCB可支持多重继承。
差别当然有,而且不少,其它的不说,单OOP的差别就有以下..... 1、BCB可Public/Protected/private的继承父类,而D只能Public的继承父类。 (如果只能Public的继承父类,将导致子类一定大于父类,而不能屏蔽父类的方法,这对面向对象来说是不利的。) 2、BCB可真正的写自己的类,而不用一定要从TObject来继承。 (在写一个小型的类时很方便,而且实例可以生成在栈里,而不是在堆里。) 3、BCB类与简单类型用法一致,无须特殊对待。 4、D中,一个Unit文件里不同Class的变量可共访。 (这将导致编程“语言”与物理“文件”的相关性。) 5、BCB可支持多重继承。
L langer Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-22 #9 C++Builder我不是很熟,但是既然C++Builder也提供了源码,就看看它是如何 解决最基本的方法QueryInterface,AddRef及Release吧,我想你一定可以找到 答案。
M maming Unregistered / Unconfirmed GUEST, unregistred user! 2000-06-23 #10 To op: 你说的很详细,我受益非浅,我只用DELPHI用得多,C++少用, 所以算是个门外汉了,看来是得好好的学学C++了,谢谢你。 我很少看源码,所以要是考OOP的话,可能不会及格,我编的 软件多半是堆积木样的堆出来的。
To op: 你说的很详细,我受益非浅,我只用DELPHI用得多,C++少用, 所以算是个门外汉了,看来是得好好的学学C++了,谢谢你。 我很少看源码,所以要是考OOP的话,可能不会及格,我编的 软件多半是堆积木样的堆出来的。
铁 铁马小子 Unregistered / Unconfirmed GUEST, unregistred user! 2000-07-13 #11 op,Delphi对COM对象接口函数地址的计算是在编译阶段,因此接口实现的方式很灵活。 具体的你可以看看TObject.GetInterfaceEntry的实现(用汇编写的)。 另外D4以后引入的implements关键字更是妙处多多,不仅把COM对象的实现和传统的面向对象完美的结合了起来,更是自然的实现了COM的聚集,实在是方便之至。 btw,传统面向对象的多重继承是弊大于利,而COM基于接口的设计加上包容和聚集的代码重用机制才真正解决了问题。
op,Delphi对COM对象接口函数地址的计算是在编译阶段,因此接口实现的方式很灵活。 具体的你可以看看TObject.GetInterfaceEntry的实现(用汇编写的)。 另外D4以后引入的implements关键字更是妙处多多,不仅把COM对象的实现和传统的面向对象完美的结合了起来,更是自然的实现了COM的聚集,实在是方便之至。 btw,传统面向对象的多重继承是弊大于利,而COM基于接口的设计加上包容和聚集的代码重用机制才真正解决了问题。
铁 铁马小子 Unregistered / Unconfirmed GUEST, unregistred user! 2000-07-13 #12 建议看看Delphi的TComObject类是怎样在不同的情况下使用IUnknown的不同实现吧(一套是为非聚集组件写的,一套则考虑了聚集的情况)。 细想下来,利用Delphi的接口特性,即使不编写COM组件,也可以更清楚的实现扁平式的高效率的多重继承——而没有C++多重继承所有弊端的COM的多重接口继承。 再加上implements和COM的聚集,COM因此实现了代码的二进制多重继承。
建议看看Delphi的TComObject类是怎样在不同的情况下使用IUnknown的不同实现吧(一套是为非聚集组件写的,一套则考虑了聚集的情况)。 细想下来,利用Delphi的接口特性,即使不编写COM组件,也可以更清楚的实现扁平式的高效率的多重继承——而没有C++多重继承所有弊端的COM的多重接口继承。 再加上implements和COM的聚集,COM因此实现了代码的二进制多重继承。
A apartment Unregistered / Unconfirmed GUEST, unregistred user! 2000-07-13 #13 铁马小子: Delphi对COM对象接口函数地址的计算是在编译阶段, 这里的函数地址具体指的是什么?是类似于: *(IUnknown+0)=(void(__stdcall*)())TCOMObject_QueryInterface之类的计算 吗?是不是函数在该COM对象里的相对地址? 能讲一讲implements关键字的使用吗? 谢谢!
铁马小子: Delphi对COM对象接口函数地址的计算是在编译阶段, 这里的函数地址具体指的是什么?是类似于: *(IUnknown+0)=(void(__stdcall*)())TCOMObject_QueryInterface之类的计算 吗?是不是函数在该COM对象里的相对地址? 能讲一讲implements关键字的使用吗? 谢谢!
O op Unregistered / Unconfirmed GUEST, unregistred user! 2000-07-14 #14 Delphi通过“包容和聚集”来实现二进制上的多重继承,的确不错。 不过这不是Delhpi的优点,而是COM的功劳。任何开发工具都支持。 不知铁兄为什么说OOP的多重继承弊大于利? 我个人倒认为COM的这种包容和聚集有些牵强。 就好像TFrom里new一个TButton,然后输出TButton的所有方法,就说TForm继承了TButton。 (COM就是因为不支持真正的"继承"而被人当作笑柄)。 其实OOP和COM的多重继承方式各有所长,一个更灵活,一个更宏观。 哦,我的那个问题终于找到C++方式的答案了。其实我最初的想法就已经离答案不远了。 一个COM类的多个接口就相当于这个类的多个抽象父类, 如果多个抽象父类都声明了一个相同名称的纯虚函数, 那么这些函数在其相应的子类中被实现就可以了。 我原来的想法是这些纯虚函数在TCOMClass中实现,如Delhpi和BCB的默认方式: IUnKnown | IDispatch | |-----------------|-----------------| IInterface1 IInterface2 IInterface3 | | | |-----------------|-----------------| | TCOMClass ////////////////////////////////////////////////////////// 用下面这种方式,同名的纯虚函数在各自的IXXX_Impl中实现,我的问题就解决了: IUnKnown | IDispatch | |-----------------|-----------------| IInterface1 IInterface2 IInterface3 | | | IInterface1_Impl IInterface2_Impl IInterface3_Impl | | | |-----------------|-----------------| | TCOMClass 其实我认为这种方式更好,以后我可以把各自的接口放在各个Unit中实现, 这样有利于大型项目的开发。
Delphi通过“包容和聚集”来实现二进制上的多重继承,的确不错。 不过这不是Delhpi的优点,而是COM的功劳。任何开发工具都支持。 不知铁兄为什么说OOP的多重继承弊大于利? 我个人倒认为COM的这种包容和聚集有些牵强。 就好像TFrom里new一个TButton,然后输出TButton的所有方法,就说TForm继承了TButton。 (COM就是因为不支持真正的"继承"而被人当作笑柄)。 其实OOP和COM的多重继承方式各有所长,一个更灵活,一个更宏观。 哦,我的那个问题终于找到C++方式的答案了。其实我最初的想法就已经离答案不远了。 一个COM类的多个接口就相当于这个类的多个抽象父类, 如果多个抽象父类都声明了一个相同名称的纯虚函数, 那么这些函数在其相应的子类中被实现就可以了。 我原来的想法是这些纯虚函数在TCOMClass中实现,如Delhpi和BCB的默认方式: IUnKnown | IDispatch | |-----------------|-----------------| IInterface1 IInterface2 IInterface3 | | | |-----------------|-----------------| | TCOMClass ////////////////////////////////////////////////////////// 用下面这种方式,同名的纯虚函数在各自的IXXX_Impl中实现,我的问题就解决了: IUnKnown | IDispatch | |-----------------|-----------------| IInterface1 IInterface2 IInterface3 | | | IInterface1_Impl IInterface2_Impl IInterface3_Impl | | | |-----------------|-----------------| | TCOMClass 其实我认为这种方式更好,以后我可以把各自的接口放在各个Unit中实现, 这样有利于大型项目的开发。