zoukankan      html  css  js  c++  java
  • [转] C++虚函数与虚函数表

    http://www.cnblogs.com/Ripper-Y/archive/2012/05/15/2501930.html

    http://blog.csdn.net/haoel/article/details/1948051/

    多态性可分为两类:静态多态和动态多态。函数重载和运算符重载实现的多态属于静态多态,动态多态性是通过虚函数实现的。

    每个含有虚函数的类有一张虚函数表(vtbl),表中每一项是一个虚函数的地址, 也就是说,虚函数表的每一项是一个虚函数的指针。

    没有虚函数的C++类,是不会有虚函数表的。

    两张图:

     class Base {
     public:
         virtual void f() { cout << "Base::f" << endl; }
         virtual void g() { cout << "Base::g" << endl; }
         virtual void h() { cout << "Base::h" << endl; }
     };

     class Derived : public Base
     {
     public:
         virtual void f() { cout << "Derived::f" << endl; }
     };

     typedef void(*Fun)(void);

     int main(int argc, char *argv[])
     {
         Base b;
         Derived d;
         Fun pFun = NULL;

         // Invoke the first virtual function
         // Base
         int **pVtab = reinterpret_cast<int **>(&b);
         pFun = reinterpret_cast<Fun>(pVtab[0][0]);
         (pFun) ();

    }

    安全性

     

    每次写C++的文章,总免不了要批判一下C++。这篇文章也不例外。通过上面的讲述,相信我们对虚函数表有一个比较细致的了解了。水可载舟,亦可覆舟。下面,让我们来看看我们可以用虚函数表来干点什么坏事吧。

     

    一、通过父类型的指针访问子类自己的虚函数

    我们知道,子类没有重载父类的虚函数是一件毫无意义的事情。因为多态也是要基于函数重载的。虽然在上面的图中我们可以看到Base1的虚表中有Derive的虚函数,但我们根本不可能使用下面的语句来调用子类的自有虚函数:

     

              Base1 *b1 = new Derive();

                b1->f1();  //编译出错

     

    任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法,所以,这样的程序根本无法编译通过。但在运行时,我们可以通过指针的方式访问虚函数表来达到违反C++语义的行为。(关于这方面的尝试,通过阅读后面附录的代码,相信你可以做到这一点)

     

    二、访问non-public的虚函数

    另外,如果父类的虚函数是private或是protected的,但这些非public的虚函数同样会存在于虚函数表中,所以,我们同样可以使用访问虚函数表的方式来访问这些non-public的虚函数,这是很容易做到的。

  • 相关阅读:
    第01组 Beta冲刺(5/5)
    第01组 Beta冲刺(4/5)
    第01组 Beta冲刺(3/5)
    第01组 Beta冲刺(2/5)
    第01组 Beta冲刺(1/5)
    2019 SDN上机第6次作业
    SDN课程阅读作业(2)
    2019 SDN上机第5次作业
    第01组 Alpha事后诸葛亮
    第01组 Alpha冲刺(6/6)
  • 原文地址:https://www.cnblogs.com/qiangxia/p/4284214.html
Copyright © 2011-2022 走看看