读C++虚函数表及C++对象的内存布局笔记

C++虚函数表解析:http://blog.csdn.net/haoel/article/details/1948051

C++对象的内存布局(上):http://blog.csdn.net/haoel/article/details/3081328

C++对象的内存布局(下):http://blog.csdn.net/haoel/article/details/3081385


C++虚函数表解析

1.一般继承(无虚函数覆盖

  • 虚函数按照其声明顺序存放于表中。
  • 父类的虚函数在子类的虚函数前面

2.一般继承(有虚函数覆盖)

  • 覆盖的f()函数被放到了虚表中原来父类虚函数的位置。
  • 没有被覆盖的函数依旧。

//涵盖上面两点的例子
#include <iostream>
using namespace std;
 
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:
    void f(){ cout << "Derived::f" << endl;}
    virtual void f1() { cout << "Derived::f1" << endl;}
    virtual void g1() { cout << "Derived::g1" << endl;}
    virtual void h1() { cout << "Derived::h1" << endl;}
};
 
int main(void)
{
    typedef void(*Fun)(void);
    Base *b;
    Base B;
    Derived D;
    b = &D;
    
    Fun pFun = NULL;
    cout << "虚函数表地址:" << (int*)(b) << endl;
    cout << "虚函数表 — 第一个函数地址:" << (int*)*(int*)(b) << endl;
 
    // Invoke the first virtual function 
    pFun = (Fun)*((int*)*(int*)(b));
    pFun();
    pFun = (Fun)*((int*)*(int*)(b)+1);
    pFun();
    pFun = (Fun)*((int*)*(int*)(b)+2);
    pFun();
    pFun = (Fun)*((int*)*(int*)(b)+3);
    pFun();
    pFun = (Fun)*((int*)*(int*)(b)+4);
    pFun();
    pFun = (Fun)*((int*)*(int*)(b)+5);
    pFun();
    cout << (Fun)*((int*)*(int*)(b)+6) << endl;
 }
输出
虚函数表地址:0xbfcdefcc
虚函数表 — 第一个函数地址:0x8048fa8
Derived::f
Base::g
Base::h
Derived::f1
Derived::g1
Derived::h1
1//为何是1而不是0。。。在“C++虚函数表解析”中附录二的例程中最后一个是0.


3.多重继承(无虚函数覆盖)(针对子类实例中的虚函数表)

  • 每个父类都有自己的虚表。
  • 子类的成员函数被放到了第一个父类的表中。(所谓的第一个父类是按照声明的顺序来判断的)。

4.多重继承(有虚函数覆盖)(针对子类实例中的虚函数表)

  • 覆盖的f()函数被放到了每个虚表中原来父类虚函数的位置。

5.安全性

  • 通过父类型的指针访问子类自己的虚函数
  • 访问non-public的虚函数

C++对象的内存布局(上)

1.对象的影响因素

  • 成员变量
  • 虚函数(产生虚函数表)
  • 单一继承(只继承于一个类)
  • 多重继承(继承多个类)
  • 重复继承(继承多个父类中其父类有相同的超类)
  • 虚拟继承(使用Virtual方式继承,为了保证继承后父类的内存布局只会存在一份)

2.单一的一般继承

  • 虚函数表在最前面的位置
  • 成员变量根据其继承和声明顺序依次放在后面。
  • 在单一的继承中,被overwrite的虚函数在虚函数表中得到了更新。

3.多重继承

  • 每个父类都有自己的虚函数表。
  • 子类的成员函数被放到了第一个父类的表中。
  • 内存布局中,其父类布局依次按声明的顺序排列。
  • 每个父类的虚表中的f()函数都被overwrite成了子类的f()。这样做就是为了解决不同的父类类型的指针指向同一个子类实例,而能够调用到实际的函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值