正文

不要VFT实现虚函数的效果(转)2007-05-25 01:05:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/qiutao/26122.html

分享到:

class CMyWnd : public CWindowImpl<CMyWnd>{ ...}; 这样作是合法的,因为C++的语法解释说即使CMyWnd类只是被部分定义,类名CMyWnd已经被列入递归继承列表,是可以使用的。 #include <iostream>using std::cout;template <class T>class B1{public:         void SayHi()         {                T* pT = static_cast<T*>(this);   // HUH?? 我将在下面解释                 pT->PrintClassName();        }protected:        void PrintClassName()     {         cout << "This is B1\n";     }}; class D1 : public B1<D1>{        // No overridden functions at all}; class D2 : public B1<D2>{public:     void PrintClassName()   {       cout << "This is D2\n";     }}; int main(){        D1 d1;        D2 d2;         d1.SayHi();    // prints "This is B1"        d2.SayHi();    // prints "This is D2"    system("pause");}//static_cast<T*>(this) 就是窍门所在。//它根据函数调用时的特殊处理将指向B1类型的指针this指派为D1或D2类型指针,因为模板代码是在编译其间生成的,所以只要编译器生成正确的继承列表,这样指派就是安全的。(如果你写成:class D3 : public B1<D2> 就会有麻烦) 之所以安全是因为this对象只可能是指向D1或D2(在某些情况下)类型的对象,不会是其他的东西。注意这很像C++的多态性(polymorphism),只是SayHi()方法不是虚函数。 要解释这是如何工作的,首先看对每个SayHi()函数的调用,在第一个函数调用,对象B1被指派为D1,所以代码被解释成:void B1<D1>::SayHi(){ D1* pT = static_cast<D1*>(this); pT->PrintClassName();} 由于D1没有重载PrintClassName(),所以查看基类B1,B1有PrintClassName(),所以B1的PrintClassName()被调用。 现在看第二个函数调用SayHi(),这一次对象被指派为D2类型,SayHi()被解释成:void B1<D2>::SayHi(){ D2* pT = static_cast<D2*>(this); pT->PrintClassName();} 这一次,D2含有PrintClassName()方法,所以D2的PrintClassName()方法被调用。 这种技术的有利之处在于: 不需要使用指向对象的指针。 节省内存,因为不需要虚函数表。 因为没有虚函数表所以不会发生在运行时调用空指针指向的虚函数。 所有的函数调用在编译时确定(译者加:区别于C++的虚函数机制使用的动态编连),有利于编译程序对代码的优化。 节省虚函数表在这个例子中看起来无足轻重(每个虚函数只有4个字节),但是设想一下如果有15个基类,每个类含有20个方法,加起来就相当可观了。

阅读(2507) | 评论(0)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

暂无评论
您需要登录后才能评论,请 登录 或者 注册