虚函数表是个什么鬼?

在多重继承里的虚函数表可以在vs里面看到,如下

有一个基类就有一张表,可以通过

    int** pVtab = (int**)&d;

    pFun = (Fun)pVtab[0][0];来访问每一个虚函数,如下代码:
// pvtable1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>

using namespace std;

class Base1 {

public:

    Base1(){ cout << "Base1::Base1()" << endl; }
    ~Base1(){ cout << "Base1::~Base1()" << endl; }

    virtual void f() { cout << "Base1::f" << endl; }

    virtual void g() { cout << "Base1::g" << endl; }

    virtual void h() { cout << "Base1::h" << endl; }

};

class Base2 {

public:
    Base2(){ cout << "Base2::Base2()" << endl; }
    ~Base2(){ cout << "Base2::~Base2()" << endl; }

    virtual void f() { cout << "Base2::f" << endl; }

    virtual void g() { cout << "Base2::g" << endl; }

    virtual void h() { cout << "Base2::h" << endl; }

};

class Base3 {

public:
    Base3(){ cout << "Base3::Base3()" << endl; }
    ~Base3(){ cout << "Base3::~Base3()" << endl; }

    virtual void f() { cout << "Base3::f" << endl; }

    virtual void g() { cout << "Base3::g" << endl; }

    virtual void h() { cout << "Base3::h" << endl; }

};

class Derive : public Base1, public Base2, public Base3 {

public:
    Derive(){ cout << "Derive::Derive()" << endl; }
     ~Derive(){ cout << "Derive::~Derive()" << endl; }

    virtual void f() { cout << "Derive::f" << endl; }

    virtual void g1() { cout << "Derive::g1" << endl; }

};

typedef void(*Fun)(void);

int doIt()
{

    Fun pFun = NULL;

    Derive d;

    int** pVtab = (int**)&d;

    //Base1‘s vtable

    //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+0);

    pFun = (Fun)pVtab[0][0];

    pFun();

    //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+1);

    pFun = (Fun)pVtab[0][1];

    pFun();

    //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+2);

    pFun = (Fun)pVtab[0][2];

    pFun();

    //Derive‘s vtable

    //pFun = (Fun)*((int*)*(int*)((int*)&d+0)+3);

    pFun = (Fun)pVtab[0][3];

    pFun();

    //The tail of the vtable

    pFun = (Fun)pVtab[0][4];

    cout<<pFun<<endl;

    //Base2‘s vtable

    //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);

    pFun = (Fun)pVtab[1][0];

    pFun();

    //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);

    pFun = (Fun)pVtab[1][1];

    pFun();

    pFun = (Fun)pVtab[1][2];

    pFun(); 

    //The tail of the vtable

    pFun = (Fun)pVtab[1][3];

    cout<<pFun<<endl;

    //Base3‘s vtable

    //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+0);

    pFun = (Fun)pVtab[2][0];

    pFun();

    //pFun = (Fun)*((int*)*(int*)((int*)&d+1)+1);

    pFun = (Fun)pVtab[2][1];

    pFun();

    pFun = (Fun)pVtab[2][2];

    pFun(); 

    //The tail of the vtable

    pFun = (Fun)pVtab[2][3];

    cout<<pFun<<endl;

    cout<<sizeof(d)<<endl;

    return 0;

}

int _tmain(int argc, _TCHAR* argv[])
{
    doIt();
    return 0;
}

运行结果如下:

最后用sizeof获取对象的大小等于成员变量的大小加上虚函数表指针的大小

时间: 2024-11-14 12:54:13

虚函数表是个什么鬼?的相关文章

单继承与多继承中的虚函数表和虚函数指针

首先,我们了解一下何为单继承,何为多继承?? 单继承:一个子类只有一个直接父类. 多继承:一个子类有两个或多个直接父类. 单继承中的虚函数表分析: 示例程序: #include <iostream> using namespace std; typedef void(*FUNC)(); class Base { public: virtual void func1() { cout << "Base::func1()" << endl; } virt

C++ 虚函数表解析

转自陈浩的博客 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以看看相关的C++的书籍.在这篇文章中,我只想从虚函数的实现

C++虚函数表剖析

关键词:虚函数.虚表,虚表指针,动态绑定,多态 一.概述 为了实现C++的多态,C++使用了一种动态绑定的技术. 这个技术的核心是虚函数表(下文简称虚表).本文介绍虚函数表是怎样实现动态绑定的. 二.类的虚表 每一个包括了虚函数的类都包括一个虚表. 我们知道,当一个类(A)继承还有一个类(B)时.类A会继承类B的函数的调用权.所以假设一个基类包括了虚函数,那么其继承类也可调用这些虚函数,换句话说,一个类继承了包括虚函数的基类.那么这个类也拥有自己的虚表. 我们来看下面的代码. 类A包括虚函数vf

C++ 虚函数表解析(转)

转自:http://blog.csdn.net/haoel 前言 C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有"多种形态",这是一种泛型技术.所谓泛型技术,说白了就是试图使用不变的代码来实现可变的算法.比如:模板技术,RTTI技术,虚函数技术,要么是试图做到在编译时决议,要么试图做到运行时决议. 关于虚函数的使用方法,我在这里不做过多的阐述.大家可以看看相关的C

C++学习之虚函数表及调用规范

在支付工具想做社交,即时通讯工具想做app市场,英语字典想做新闻社交的今天,创造这些怪象的公司要求程序员懂得更多几乎是理所当然的,毕竟现在大家什么都想做.这不,正值招聘季,实验室的几位学长也是一直在讨论各种问题,发现对于C++语言而言,问的最多的还是虚函数表和STL. STL的考点至少是实用的,哪怕要求你读过源码,也并不过分,毕竟知根知底才能更好地应用.但要求程序员掌握对象模型着实拎不清,因为这几乎用不到,远没有在设计模式上投入时间实在,或许它们最希望的是拿批发价招语言专家... 我已经近2年没

类虚函数表原理实现分析(当我们将虚表地址[n]中的函数替换,那么虚函数的实现就由我们来控制了)

原理分析 当调用一个虚函数时, 编译器生成的代码会调用 虚表地址[0](param1, param2)这样的函数. 已经不是在调用函数名了. 当我们将虚表地址[n]中的函数实现改为另外的函数, 虚函数的实现就由我们来控制了. 实验 根据虚表原理, 实验一下修改自己程序的虚函数表项地址. 使编译器生成的代码执行一个虚函数A时, 执行的是我们自己定义的非虚函数B. 知识点 * 使用union赋值, 绕过编译器函数与变量强转赋值的限制 * 类成员函数指针的执行 * 修改和恢复自己的代码段属性 * 虚函

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;} }; typedef void (*Fun)(void); int main(){ Base

C++中3种多态实现机制之虚函数表

上期我们简单的讲解了利用RTTI来实现多肽,这期我们就来聊聊利用虚函数的方法来实现多肽. 1.什么是虚函数 在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体}:,实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数 2.实现多肽的条件 简单的说就是:基类的指针或引用指向子类对象,当子类中成员函数和基类成员函数:函数名相同,参数列表相同,返回值相同,并且基类该函数为虚函数时,基类

《COM原理与应用》题外话——C++虚函数表和delete this

delete this看起来非常的奇怪,我记得在<C++ Primer>中提到过delete this,但是我已经忘了在哪了,也一直没有找到(因为没有电子版,所以一直没找到~).<C++ Primer>中提到的是在析构函数中使用delete this会造成析构函数的无限调用,最终造成栈溢出.我也在网上看了一些,很多人觉得不该使用delete this,因为会引起一些问题.但是delete this也挺有用处的,就和goto语句一样,不应该被一棍子打死(goto语句其实怪好用的:-D