zoukankan      html  css  js  c++  java
  • C++虚函数和虚函数表

    前导

    在上面的博文中描述了基类中存在虚函数时,基类和派生类中虚函数表的结构。

    在派生类也定义了虚函数时,函数表又是怎样的结构呢?

    先看下面的示例代码:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class A
     6 {
     7 public:
     8     virtual void funcA(){ cout<<"A"<<endl; }
     9 };
    10 
    11 class B
    12 {
    13 public:
    14     virtual void funcB(){ cout<<"B"<<endl; }
    15 };
    16 
    17 class C : public A, public B
    18 {
    19 public:
    20     virtual void funcC(){ cout<<"C"<<endl; }
    21 };
    22 
    23 int main()
    24 {
    25     C c;
    26     cin.get();
    27 }

    class A 和 class B 都有一个虚函数,然后 class C 继承 A 和 B。在VS2010中,查看变量:

    如图所示,局部变量中只显示了从 A 和 B 继承来的虚函数表地址。那么 C 自己的虚函数呢?

    首先查看 A 虚函数表地址:

     

    可以看到,虚函数表中的前4个字节就是 A 中虚函数的地址(红色框)。同时后面又紧跟着4个有内容的字节,然后才是表示虚函数表结束的4个0。

    可以猜测,这应该就是 C 的虚函数地址。再来看一下 B 的虚函数表:

    可以看到,虚函数表中只有 B 的虚函数这一个地址。为了证实上面的猜测,将函数指针从 A::funcA 向后递增一次,应该就是对 C::funC的调用:

    int main()
    {
        typedef void(*pfun)();
    
        C c;
        auto p = &c;
    
        auto funcA = (pfun)**((int**)p);
        funcA(); // 调用 A::funcA
    
        auto funcC = (pfun)*(*((int**)p) + 1);
        funcC(); // 调用 C::funcC
    
        cin.get();
    }

    输出结果: 证实了我们的猜测。

    如果在增加一个 class D 继承 C 呢?

    class D : public C
    {
        virtual void funcD() {}
    };
    
    int main()
    {
        D d;
    
        cin.get();
    }

    变量:

    和 C 中展示的一样,只有两个虚函数表。

    内存:

    可以看到,在 A::funcA 后还有两个地址,可以推测就是 C::funcC 和 D::funcD 的地址了。

    总结:

    1、在多继承中,派生类的虚函数表的个数由它所继承的“顶层的”基类的个数决定:有多少个这样的基类,就有多少个虚函数表。

    2、派生类自己的虚函数被追加到第一个虚函数表的后面。

    例如下面的继承:

    假设每个类 X 都有一个 funcX 虚函数,那么G中虚函数和虚函数表如下:

  • 相关阅读:
    C++类中的封装-9
    递归神经网络
    卷积神经网络
    Tensorflow人工智能神经网络学习
    右键弹出菜单 并动态新增菜单子项
    sql 列转行
    sql 删除表中某字段的重复数据
    疑难问题解决
    jquery ashx交互 返回list 循环json输入信息
    jquery 控件赋值
  • 原文地址:https://www.cnblogs.com/kohlrabi/p/6089148.html
Copyright © 2011-2022 走看看