对象的多态技术

  C++的虚函数机制,是通过一个虚函数表存放函数指针实现的,一旦子类重载了虚函数,就替换掉表里的指针。COM的原理与此很类似,其中Interface可以看作纯虚类。C++是静态语言,函数表没有自描述性,调用代码完全是编译器由指针偏移量编译得到的硬编码。也就是说,虚函数表是定长的,即使是子类没有实现的函数,也需要父类的函数指针来占位。

  而Ruby等新一代动态语言,因为包含元数据,可以根据方法的名称进行查找。子类实现了几个虚函数,它的查找表就有多长,找不到再扔给父类继续查找。

  思路上,两者都是插入一个中间层,拦截外界对方法的调用,按照具体的类信息指定实际执行的代码。两者也有差别:动态语言因为涉及到字符串比较,查找效率相对差,而C++运行效率更高;但如果一个C++的父类提供成千上万的虚方法接口,即使子类只实现其中一小部分,也必须带着一个巨大的函数表,这显然造成了空间浪费。

  典型的,GUI架构如果采用虚函数机制,即使再小的对话框,例如‘确认取消’,甚至是只需要实现OnClick()的一个按钮类,由于是从Window类继承下来的,都必须带着一个存放几百甚至上千函数指针的函数表。

  为了对付这种情况,MFC没有使用虚函数,而定义了一大堆宏进行事件消息分发,虽然语法风格很丑陋,但保证了效率;而.net框架,发展出delegate机制,呵呵,兜了一圈,我们又回到纯C的回调函数风格了。

  参考资料很多:元数据、反射和delegate机制的资料都源于网上;C++和COM技术参考这两本:《Inside The C++ Object Model》和《COM原理与应用》。

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.