C++重要性质04:虚拟函数与动态绑定

来源:互联网 发布:三线性优化开不开 编辑:程序博客网 时间:2024/05/17 22:26

     序:大学四年浑浑噩噩,光阴虚度;值此毕业之际,如梦方醒;然亦无所悔恨,既有所悟,惟勤勉耳。近来研习《深入浅出MFC》,受益良多,故而摘抄一二,置此博文之中,以备不时翻阅。小子不才,无所增益,学而践之而已。此文摘自《深入浅出MFC》第二章C++的重要性质。 

   【虚拟函数与动态绑定】

     虚拟函数是C++语言的多态性质以及动态绑定的关键,那么虚拟函数是怎么实现的?如果能够了解C++编译器对于虚拟函数的实现方式,我们就能够知道为什么虚拟函数可以做到动态绑定。

     为了达到动态绑定(后期绑定)的目的,C++ 编译器通过某个表格,在执行时期「间接」调用实际上欲绑定的函数。这样的表格称为虚拟函数表(常被称为vtable)。每一个「内含虚拟函数的类别」,编译器都会为它做出一个虚拟函数表,表中的每一笔元素都指向一个虚拟函数的地址。此外,编译器当然也会为类别加上一项成员变量,一个指向该虚拟函数表的指针(常被称为vptr)。

           class Class1
           {

            public :
                 m_data1;
                 m_data2;
                 memfunc();
                 virtual vfunc1();
                 virtual vfunc2();
                 virtual vfunc3();
           };

     Class1 对象实体在内存中占据这样的空间:


     每一个由此类别衍生出来的对象,都有这么一个vptr。我们通过这个对象调用虚拟函数,事实上是通过vptr找到虚拟函数表,再找出虚拟函数的真正地址。奥妙在于这个虚拟函数表以及这种间接调用方式。

      虚拟函数表的内容是依据类别中的虚拟函数声明次序一一填入函数指针的。衍生类别会继承基础类别的虚拟函数表(以及所有其它可以继承的成员),当我们在衍生类别中改写虚拟函数时,虚拟函数表就受了影响:表中元素所指的函数地址将不再是基础类别的函数地址,而是衍生类别的函数地址。

           class Class2 : public Class1
           {

            public :
                 m_data3;
                 memfunc();
                 virtual vfunc2();
           };

                       

      于是,一个「指向Class1所生对象」的指针,所调用的vfunc2 就是Class1::vfunc2(),而一个「指向Class2 所生对象」的指针,所调用的vfunc2 就是Class2::vfunc2。动态绑定机制,在执行时期,根据虚拟函数表,做出了正确的选择。






0 0
原创粉丝点击