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的虚函数,这是很容易做到的。

最新文章

  1. 理解Docker(2):Docker 镜像
  2. mybatis+MySQL--CRUD
  3. expr 命令
  4. sql date()函数
  5. Android 中文API (69) —— BluetoothAdapter[蓝牙]
  6. Android开发人员必知的开发资源
  7. 【linux】linux下vi命令的使用
  8. 抓包工具Charles基本用法
  9. php-fpm无法使用系统环境变量的解决方法
  10. 【ARTS】01_11_左耳听风-20190121~20190127
  11. 小心踩雷,一次Java内存泄漏排查实战
  12. 5.Xilinx RapidIO核例子工程源码分析
  13. 网络设备Web登录检测工具device-phamer
  14. MultipleRegularExpressionAttribute MVC中扩展自定义验证规则
  15. [UE4]角色增加挂点、增加枪
  16. PasswordlessAPI
  17. git add -A和git add . 的区别
  18. 自己动手搭建Git服务器-Gitblit
  19. c++:error2019,无法解析的外部命令blabla~
  20. Linux中关机,重启,注销命令

热门文章

  1. PHP 用户注册
  2. 小记搭建WAPM运行ThinkPHP时所需要的配置
  3. assert sys.modules[modname] is old_mod
  4. C# 程序性能提升篇-2、类型(字段类型、class和struct)的错误定义所影响性能浅析
  5. 【Java】理解 UDDI 注册中心的 WSDL
  6. MYSQL的硬盘IO过高引起的CPU过高判断
  7. OPENFILER记下,有空再玩之,ISCSI,以后网络起来了,速度还是应该可以的
  8. NXP LPC11xx I2C Slave 从机程序
  9. 数据结构(线段树):HDU 5649 DZY Loves Sorting
  10. 重新注册IE组件