单继承下的虚表布局

在C++中,多态表示 “以一个公有基类的指针或引用,寻址出一个派生类对象” 。

假如有调用 ptr->get_c() ,其中ptr是基类指针,get_c()是一个虚函数。要在执行期能正确调用get_c()的实例,我们需要知道:

1.ptr所指对象的真正类型,以便我们选择正确的get_c()实例。

2.get_c()实例的位置,以便我们能够调用他。

在实现上,编译时期会构建出来一张虚表,表格中有程序的虚函数的执行期地址。

为了找到这个表格,每一个类对象被安插一个由编译器产生的指针,指向虚表。

为了找到函数地址,每一个虚函数被指派一个表格索引值。

如果有代码例子:

class A
{
protected:
    int a;
public:
    A(const int a) :a(a){}
    virtual ~A();
    virtual int pure_v() = 0; //纯虚函数
    virtual int get_b(){ return 0; }
    virtual int get_c(){ return 0; }
};
class B :public A
{
protected:
    int b;
public:
    B(int a = 0, int b = 0):A(a),b(b){}
    ~B();
    int pure_v();
    int get_b(){ return b; }
};
class C :public B
{
protected:
    int c;
public:
    C(int a = 0, int b = 0, int c = 0) :B(a, b), c(c){}
    ~C();
    int pure_v();
    int get_c(){ return c; }
};

一个类只会有一张虚表。每个表内含其对应类对象中三类虚函数,这三类包括:

1.这一类所定义的虚函数实例或改写自基类的虚函数实例。如例子中Calss B中的get_b()。

2.继承自基类的已被改写过的函数实例。如例子中Calss C的虚表中会有get_b(),在C中不改写,而在B中已被改写过。

3.一个纯虚函数的实例。如Class B中的pure_v()。

接下来我们看类A,B,C的虚表布局。

对于A a; 布局如下:(博主是用visio画的,有点丑- -)

_vptr是编译时期产生的虚表指针。

slot 0通常是指出每个类所关联的type_info object(用以支持RTTI)。

A的虚析构被指派为solt 1。纯虚函数被指派为solt 2,但A中的纯虚函数没有定义,如果意外调用了此函数,通常的操作是结束这个程序。

get_b()被指派slot ,get_c()被指派slot 4。

对于B:A b; 布局如下:

B的虚表中在solt 1指出析构函数。A中的纯虚函数有了定义,所以在slot 2指出pure_()。

自己的get_b()函数实例地址放在solt 3。继承自A的get_c()函数实例地址放在solt 4。

对于C:B c; 布局如下:

solt 1放置析构函数地址,solt 2放置pure_v()函数地址,solt 3放置继承自B的get_b()的函数地址,solt 4放置自己的get_c()函数地址。

现在再来看调用ptr->get_c();

*在每次调用get_c()时,我们并不知道ptr所指对象的真正类型。但是我知道通过ptr可以存取到该对象的虚表。

*虽然我不知道哪一个get_c()函数实例会被调用,但是我知道每一个get_c()的函数实例地址都被放在solt 4中。

通过这些信息,编译器可以把调用改写为:

(ptr->_vptr[4])(ptr);

从而在执行期调用正确的函数实例。

时间: 2024-10-14 06:48:55

单继承下的虚表布局的相关文章

虚继承之单继承的内存布局(VC在编译时会把vfptr放到类的头部,这和Delphi完全一致)

C++2.0以后全面支持虚函数与虚继承,这两个特性的引入为C++增强了不少功能,也引入了不少烦恼.虚函数与虚继承有哪些特性,今天就不记录了,如果能搞了解一下编译器是如何实现虚函数和虚继承,它们在类的内存空间中又是如何布局的,却可以对C++的了解深入不少.这段时间花了一些时间了解这些玩意,搞得偶都,不过总算有些收获,嘿嘿. 先看一段代码class A{      virtual aa(){};}; class B : public virtual  A{      char j[3];      

C++中的类继承之单继承&多继承&菱形继承

 C++中的类继承之单继承&多继承&菱形继承 单继承是一般的单一继承,一个子类只 有一个直接父类时称这个继承关系为单继承.这种关系比较简单是一对一的关系: 多继承是指 一个子类有两个或以上直接父类时称这个继承关系为多继承.这种继承方式使一个子类可以继承多个父类的特性.多继承可以看作是单继承的扩展.派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承.多继承下派生类的构造函数与单继承下派生类构造函数相似,它必须同时负责该派生类所有基类构造函数的调用.同时,派生类的参数个数必须包

浅谈C++非多态单继承数据布局

最近在看<深度探索C++对象模型>,打算先总结下C++中的数据布局,这篇暂时先谈谈非多态(non-polymorphic)单继承的情况: 一般而言,当我们谈及C++中的继承和多态就默认进入到其面向对象的语境中了.封装是基础,公有继承(public)是手段,然后带来运行时多态(run-time polymorphism)的弹性,通过“基类指针或引用可以透明的指向任何派生类对象”这句话来支撑着C++的面向对象体系.目的无他,无非是简化用户(这里的用户指的是类的使用者)的使用逻辑,即归一化.归一化说

C++里的继承和多态(下)——单继承、多继承、菱形继承(含虚拟函数的继承)

1.带有虚函数的类 class Base { public:                  virtual void FunTest1()                 {                                 cout << "Base::FunTest1()" << endl;                 }                  virtual void FunTest2()                 

多重虚继承下的对象内存布局

<深入C++对象模型>绝对是一本值得深读的一本书,书里多次出现一句话,“一切常规遇见虚继承,都将失效”.这是一个有趣的问题,因为C++标准容忍对象布局的实现有较大的自由,出现了各编译器厂商实现的方式不同. 今天谈谈visual studio2013多重虚继承下对象布局.有错不要客气,不要吝啬你的留言,请直接开喷. class y和class z都是从class x虚继承来的子类(也叫派生类),class A是class y和class z的多重继承子类.为了简化问题,下面的data membe

C++对象模型:单继承,多继承,虚继承

C++对象模型 有两个概念可以解释C++对象模型: 语言中直接支持面向对象程序设计的部分.对于各种支持的底层实现机制. 单继承(父类含虚函数) 1 #include <iostream> 2 #include<vector> 3 using namespace std; 4 5 class Base 6 { 7 public: 8 void fun1(){ cout << "Base fun1" << endl; } 9 virtual

c++继承汇总(单继承、多继承、虚继承、菱形继承)

一.C++中的对象模型 1. 概念 语言中直接支持面向对象程序设计的部分: 对于各种支持的底层实现机制.(没看懂……) 2. 类中的成员分类 a) 成员函数 i. static function ii. non static function iii. virtual function b)  数据成员 i. static member data ii. non static member data 3. C++对象模型 a) 类对象内存布局中的包括 i. non static member d

c/c++: c++继承 内存分布 虚表 虚指针 (转)

http://www.cnblogs.com/DylanWind/archive/2009/01/12/1373919.html 前部分原创,转载请注明出处,谢谢! class Base { public:  int m_base; }; class DerivedA: public Base { public:  int m_derivedA; }; class DerivedB: public Base { public:  int m_derivedB; }; class DerivedC

【转】c++继承中的内存布局

今天在网上看到了一篇写得非常好的文章,是有关c++类继承内存布局的.看了之后获益良多,现在转在我自己的博客里面,作为以后复习之用. ——谈VC++对象模型(美)简.格雷程化    译 译者前言 一个C++程序员,想要进一步提升技术水平的话,应该多了解一些语言的语意细节.对于使用VC++的程序员来说,还应该了解一些VC++对于C++的诠释. Inside the C++ Object Model虽然是一本好书,然而,书的篇幅多一些,又和具体的VC++关系小一些.因此,从篇幅和内容来看,译者认为本文