首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

类的对象(使用单/多继承)有多少vptr?

类的对象(使用单/多继承)有多少vptr取决于该类的继承方式和虚函数的数量。

在C++中,虚函数表(vtable)是一个指针数组,其中每个指针指向一个虚函数。虚函数表的作用是在运行时动态地确定对象的类型,并调用相应的虚函数。每个类对象都有一个指向其虚函数表的指针,称为vptr。

对于单继承的类,每个对象只有一个vptr,它指向该类的虚函数表。虚函数表中的每个函数指针对应该类的一个虚函数,以及其基类中的虚函数。如果该类没有定义任何虚函数,则不会为该类创建虚函数表。

对于多继承的类,每个对象有一个指向虚函数表的指针,该指针对应于该类的每个基类。因此,一个多继承的类可能有多个vptr,每个基类一个。

总之,一个类的对象的vptr数量取决于该类的继承方式和虚函数的数量。在单继承的情况下,每个对象只有一个vptr,而在多继承的情况下,每个对象有多个vptr。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【C++】继承 ① ( 面向对象特点 | 之间关系 | 继承继承 | 继承关系特性 )

一、面向对象相关概念 1、面向对象特点 面向对象 4 大特点 : 抽象 : 只关注对象功能和行为 , 而不过问实现具体细节 ; 封装 : 将对象 属性 和 方法 封装在一起 ; 继承 : 新继承现有...关系 : 对象之间存在关系 ; 关联关系 Association : 一个中定义了其它对象作为 成员变量 ; 依赖关系 Dependency : 一个成员方法中使用了其它对象...; 子类 又称为 派生 ; 2、继承继承 继承继承 : A 只有一个 子类 B , 那么 该继承 就是 继承 ; A 多个子类 B1 , B2 … , 该 继承...是 继承 ; 继承 继承是指一个只能继承一个父特性和行为 ; 下面的代码中 , Child 继承了 Parent 所有公有和保护成员 , 并且可以访问它们 ; 注意 : Child...}; 继承 继承是指一个可以继承多个父特性和行为 ; 下面的代码中 , Child 继承了 Parent1 和 Parent2 所有 公有 和 保护 成员 , 并且可以访问它们 ;

19530

typescript 继承_说明继承和多态什么作用

前言 对于传统 JavaScript 程序我们会使用函数和基于原型继承来创建可重用组件,但对于熟悉使用面向对象方式程序员使用这些语法就有些棘手,因为他们用是基于继承并且对象是由构建出来...从 ECMAScript 2015,也就是 ES6 开始, JavaScript 程序员将能够使用基于面向对象方式。...我们声明了一个Person。这个3个属性、一个构造函数和一个sayHi方法。 我们使用new构造了Person一个实例。...它会调用构造函数,创建一个Person类型对象,并执行构造函数初始化它。最后通过person对象调用其sayHi方法 继承 在 TypeScript 里,我们可以使用常用面向对象模式。...基于程序设计中一种最基本模式是允许使用继承来扩展现有的

1.2K20
  • 面向对象编程-继承1.继承介绍以及继承2.继承示例3.继承4.重写父方法与调用父方法5.类属性和实例属性6.静态方法和方法

    1.继承介绍以及继承 将共性内容放在父中,子类只需要关注自己特有的内容 继承概念:在现实生活中,继承一般指的是子女继承父辈财产,在程序中,继承描述是事物之间所属关系,例如猫和狗都属于动物...说明:虽然子类没有定义__init__方法,但是父,所以在子类继承时候这个方法就被继承了,所以只要创建Bosi对象,就默认执行了那个继承过来__init__方法 总结:子类在继承时候,在定义时...,往往用来做内部事情,起到安全作用 3.继承 1.Python中继承格式如下: ?...说明:python中是可以继承,在java中叫接口           父方法、属性,子类会继承 2.如果父A和父B中,一个同名方法,那么通过子类去调用时候,调用哪个? ?...4.重写父方法与调用父方法 1.重写父方法 所谓重写,就是子类中,一个和父相同名字方法,在子类中方法会覆盖掉父中同名方法 ? 2.调用父方法 ? ?

    1.2K20

    图说C++对象模型:对象内存布局详解

    继承C++对象模型。分析C++对象在下面情形中内存布局: 继承:子类单一继承自父,分析了子类重写父虚函数、子类定义了新虚函数情况下子类对象内存布局。...继承:子类继承于多个父,分析了子类重写父虚函数、子类定义了新虚函数情况下子类对象内存布局,同时分析了非虚继承菱形继承。...4.2.表格驱动模型 这个模型在简单对象模型基础上又添加一个间接层,它把数据分成了两个部分:数据部分与函数部分,并使用两张表格,一张存放数据本身,一张存放函数地址(也即函数比成员一次寻址),...这个结果与我们对象模型符合。 5.2.继承 5.2.1一般多重继承(非菱形继承继承中(一般继承),子类会扩展父虚函数表。...7.2.下面这个空构成继承层次中,每个大小是多少

    3.9K43

    VC和GCC内成员函数指针实现研究(一)

    最近在《C++对象模型》一书里说到virtual成员函数指针,低于128被cfront编译器认为是虚表偏移量(支持子类对父函数覆盖)。...VC只是提了下单继承继承和虚继承实现方案不同,GCC没有提及,所以就专门稍微深入分析研究下他们实现机制。 以下所有代码都使用了64位编译,所以32位编译和运行结果可能有略微差异。...继承 首先是继承情况。...由此来保证调用是子类里成员函数。 好吧运行结果还是必要贴一下 image.png 图四: VC继承测试代码执行结果 GCC继承成员函数指针实现 接下来就是GCC了。...但是这种做法带来缺陷就是成员函数指针比VC消耗了一倍内存,执行结果如下: image.png 图七:GCC继承测试代码执行结果 多重继承和虚继承分析就下次再来啦。

    84530

    VC和GCC内成员函数指针实现研究(一)

    最近在《C++对象模型》一书里说到virtual成员函数指针,低于128被cfront编译器认为是虚表偏移量(支持子类对父函数覆盖)。...VC只是提了下单继承继承和虚继承实现方案不同,GCC没有提及,所以就专门稍微深入分析研究下他们实现机制。 以下所有代码都使用了64位编译,所以32位编译和运行结果可能有略微差异。...继承 首先是继承情况。...好吧运行结果还是必要贴一下 图片 图四: VC继承测试代码执行结果 GCC继承成员函数指针实现 接下来就是GCC了。GCC是怎么实现呢?同样还是祭出大杀器,反汇编。...但是这种做法带来缺陷就是成员函数指针比VC消耗了一倍内存,执行结果如下: 图片 图七:GCC继承测试代码执行结果 多重继承和虚继承分析就下次再来啦。

    52220

    sizeof 知多少? (下)

    继承 接着我们来看一下类型间继承情况,看看内存布局会有什么变化: struct cv1 { int m_1; virtual ~cv1() {}; }; struct cv2 :...public cv1 { short m_2; virtual ~cv2() {}; }; 一般而言,如果基或者继承存在虚函数表指针的话,vptr会置于类型内存布局首部(继承会复用基虚函数表指针...继承 C++还支持继承特性,一个类型可以继承于多个基(假设基分别为B1, B2, …, Bn),其中每个基都可能有成员数据及虚函数表,继承I也必须能够无缝向下转形为任一基,其内存布局一般规则如下...虚拟继承 虚拟继承偏于复杂,一般也不推荐使用,讨论虚拟继承相关内存布局实际来看意义不大,仅供兴趣朋友参考 :) 一般C++教科书中都会提一下虚拟继承,并说明一下虚拟继承目的是为了解决菱形继承导致重复基问题...,相反,GCC”合并”了虚函数表指针(vptr)和虚基表指针(vbptr), 或者说GCC只使用vptr来实现虚函数重载和虚基索引,方法是通过正向索引vptr来定位虚函数(vptr + offset

    63500

    各大框架都在使用Unsafe,到底神奇?

    Unsafe构造 Unsafe是"final",不允许继承,且构造函数是private,使用例模式来通过一个静态方法getUnsafe()来获取。...SecurityException("Unsafe"); } else { return theUnsafe; } } 在getUnsafe方法中对例模式中对象创建做了限制...只有由主加载器加载才能调用这个方法。 那么,如何获得Unsafe对象呢?...putInt用于在对象指定偏移地址处写入一个int。其他原始类型也提供对应方法。 另外,UnsafegetByte、putByte方法提供了直接在一个地址上进行读写功能。...七、CAS操作 UnsafeCAS操作可能是使用最多方法。它为Java锁机制提供了一种新解决办法,比如AtomicInteger等都是通过该方法来实现

    28820

    C语言实现面向对象原理

    不知道多少人去了解过语言发展史,早期C语言语法功能其实比较简单。随着应用需求和场景变化,C语言语法功能在不断升级变化。...因此,不建议初学者使用C语言实现面向对象,特别是在真正项目中。建议把基本功练好,再使用。 利用C语言实现面向对象方法很多,下面就来描述最基本封装、继承和多态。...以后写代码时候,要多去想想标准库文件IO操作,这样也有意识去培养面向对象编程思维。 继承 继承就是基于现有的一个去定义一个新,这样有助于重用代码,更好组织代码。...在 C 语言里面,去实现继承也非常简单,只要把基放到继承第一个数据成员位置就行了。...用 C 语言实现封装、继承,理解和实现起来比较简单,多态反而会稍微复杂一点,如果打算广泛使用多态,还是推荐转到 C++ 语言上,毕竟这层复杂性被这个语言给封装了,你只需要简单使用就行了。

    85621

    一文读懂C++虚继承内存模型

    一文读懂C++虚继承内存模型 1、前言 2、继承存在问题 3、虚继承简介 4、虚继承在标准库中使用 5、虚继承下派生内存布局解析 6、总结 1、前言 C++虚继承内存模型是一个经典问题...本文将对g++中虚继承内存模型进行详细解析。 2、继承存在问题 C++继承是指从多个直接基中产生派生能力,继承派生继承了所有父成员。...在这种机制下,不论虚基继承体系中出现了多少次,在派生中都只包含一份虚基成员。...因为这里设计比较简单,没有把虚函数加进来,虚函数的话_vptr.B或者_vptr.C下面的内存空间存储就是指向对应虚函数指针了(以下只讲_vptr.B相关内容,_vptr.C同理就不赘述了)...需要注意是,由于一个类型即可以被单继承,也可以被继承,因此即使只有继承,实体offset_to_top也会存在于每一个多态类型之中。

    1.1K20

    【C++】继承 ⑥ ( 继承构造函数和析构函数 | 类型兼容性原则 | 父指针 指向 子类对象 | 使用 子类对象 为 父对象 进行初始化 )

    一、public 公有继承 - 示例分析 1、类型兼容性原则 类型兼容性原则 : C++ " 类型兼容性原则 “ 又称为 ” 赋值兼容性原则 " ; 子类代替父 : 需要 基 ( 父 ) 对象...地方 , 都可以使用 " 公有继承 " 派生 ( 子类 ) 对象 替代 , 该 派生 ( 子类 ) 得到了 除 构造函数 和 析构函数 之外 所有 成员变量 和 成员方法 ; 功能完整性 :..." 公有继承 " 派生 ( 子类 ) 本质上 具有 基 ( 父 ) 完整功能 , 使用 可以解决问题 , 使用 公有继承派生 都能解决 ; 特别注意 : " 保护继承 " 和..." 私有继承 " 派生 , 是 不具有 基 完整功能 , 因为 最终继承派生 , 无法在 外部调用 父 公有成员 和 保护成员 ; 2、类型兼容性原则应用场景 " 类型兼容性原则..." 应用场景 : 直接使用 : 使用 子类对象 作为 父对象 使用 ; 赋值 : 将 子类对象 赋值给 父对象 ; 初始化 : 使用 子类对象 为 父对象 初始化 ; 指针 : 父指针 指向

    26520

    深入探索虚函数表(详细)

    这篇博客可能有一点点长,代码也有一点点,但是仔细阅读分析完,会对虚函数表一个深刻认识。 什么是虚函数表?        ...对于一个来说,如果类中存在虚函数,那么该类大小就会4个字节,然而这4个字节就是一个指针大小,这个指针指向虚函数表。...我们来分析这两个虚函数表,对于基虚函数表其实和上面所说虚函数表是一样自己虚函数指针,并指向自己虚函数表,重点是在于派生虚函数表是什么样子,它样子如下图所示:        ...:      这个是继承情况,然后我们看看多重继承,也就是Derive继承两个基,先看一下代码: class Base1 { public: virtual void A() { cout...如果按上面代码方式去执行,由于是非指针非引用形式,所以编译器采用了静态绑定,提前绑定了函数地址,那么就不存在指针寻址过程了;如果使用指针或引用形式,那么由于对象所属不能确定,那么编译器就无法采用静态编联

    55500

    c++头脑风暴-多态、虚继承、多重继承内存布局

    虚函数内存布局 还是先看一个包含虚函数,代码如下: #include using namespace std; class CPeople { public:...,是一样,只不过直接使用派生对象是在编译时就已经确定了是调用基还是派生虚函数,而使用指针则是在运行时才能确定。...总结一下:c++继承多态一般指运行时多态,使用指针或者引用指向一个派生对象,在非虚继承情况下,派生直接继承虚表指针,然后使用派生虚函数去覆盖基虚函数,这样派生对象通过虚表指针访问到虚函数就是派生虚函数了...,本身会生成一份虚函数表,这个虚函数表是所有对象共享,每个对象都会在构造时首先生成一个虚表指针,指向这个虚函数表,然后才是各个成员变量,所以虚函数对象会比没有虚函数一个虚表指针,虚表指针跟其他指针没有区别...,基虚表指针和成员变量在后; 多重继承时最好使用继承,否则不只是会产生令人头疼二义性问题,还会一份虚基拷贝,使用继承以后,大家共享虚基,既节约了空间,又避免了二义性问题。

    68320

    二进制学习系列-堆溢出

    Pwnable-UAF 这道题主要考察是虚函数内存地址空间以及UAF使用 所需知识: 1.虚函数内存地址空间: 在C++中,如果类中有虚函数,那么它就会有一个虚函数表指针__vfptr,在对象最开始内存数据中...之后是成员变量内存数据。 对于子类,最开始内存数据记录着父对象拷贝(包括父虚函数表指针和成员变量)。 之后是子类自己成员变量数据。 ? 继承,无虚函数重载: ?...继承虚函数重载: ?...总结 如果一个中有虚函数,那么就会建立一张虚函数表vtable,子类继承vtable,若,父vtable中私有(private)虚函数,则子类vtable中同样该私有(private)虚函数地址...vptr每个对象都会有一个,而vptable是每个一个,vptr指向vtable,一个中就算多个虚函数,也只有一个vptr;做多重继承时候,继承了多个父,就会有多个vptr 详情知识请移步:

    90841

    C++虚函数表深入探索(详细全面)

    这篇博客可能有一点点长,代码也有一点点,但是仔细阅读分析完,会对虚函数表一个深刻认识。 什么是虚函数表?        ...对于一个来说,如果类中存在虚函数,那么该类大小就会4个字节,然而这4个字节就是一个指针大小,这个指针指向虚函数表。...我们来分析这两个虚函数表,对于基虚函数表其实和上面所说虚函数表是一样自己虚函数指针,并指向自己虚函数表,重点是在于派生虚函数表是什么样子,它样子如下图所示: ?        ...这个是继承情况,然后我们看看多重继承,也就是Derive继承两个基,先看一下代码: class Base1 { public: virtual void A() { cout << "Base1...如果按上面代码方式去执行,由于是非指针非引用形式,所以编译器采用了静态绑定,提前绑定了函数地址,那么就不存在指针寻址过程了;如果使用指针或引用形式,那么由于对象所属不能确定,那么编译器就无法采用静态编联

    18.8K168

    深入探索虚函数表(详细)

    这篇博客可能有一点点长,代码也有一点点,但是仔细阅读分析完,会对虚函数表一个深刻认识。 什么是虚函数表?        ...对于一个来说,如果类中存在虚函数,那么该类大小就会4个字节,然而这4个字节就是一个指针大小,这个指针指向虚函数表。...我们来分析这两个虚函数表,对于基虚函数表其实和上面所说虚函数表是一样自己虚函数指针,并指向自己虚函数表,重点是在于派生虚函数表是什么样子,它样子如下图所示: image.png...: image.png      这个是继承情况,然后我们看看多重继承,也就是Derive继承两个基,先看一下代码: class Base1 { public: virtual void A...如果按上面代码方式去执行,由于是非指针非引用形式,所以编译器采用了静态绑定,提前绑定了函数地址,那么就不存在指针寻址过程了;如果使用指针或引用形式,那么由于对象所属不能确定,那么编译器就无法采用静态编联

    1.2K80

    【Ruby高级技术】对面向对象控制访问,包括继承常量深入理解和使用

    文章目录 面向对象 控制访问 继承 常量 面向对象 class Box def initialize(w,h) @width, @height = w, h end end...例如,我们使用关键字来定义Box,如下所示: class Box code end 实例变量是类属性,当使用创建对象时,这些属性将成为对象属性。...# (NoMethodError) 继承 继承是面向对象编程中最重要概念之一。...在多重继承中,只有接口部分是可继承。 在创建时,程序员可以直接指定新继承自现有成员,这样就不必从头开始编写新数据成员和成员函数。现有称为基或父,新称为派生或子类。...如果对象已被冻结,则此方法将返回true;否则,它将返回一个假值。 常量 通过将直接数值或字符串值赋给变量,可以在中定义常量。不需要使用@或@@来定义常量。按照惯例,常数名称是大写

    64230

    c语言实现面向对象编程

    以后写代码时候,要多去想想标准库文件IO操作,这样也有意识去培养面向对象编程思维。 继承继承就是基于现有的一个去定义一个新,这样有助于重用代码,更好组织代码。...在 C 语言里面,去实现继承也非常简单,只要把基放到继承第一个数据成员位置就行了。...这样的话,基所有属性和方法都可以被继承继承!...2、在构造函数中设置vptr: 在每一个对象实例中,vptr 必须被初始化指向其 vtbl。最好初始化位置就是在构造函数中。事实上,在构造函数中,C++ 编译器隐式创建了一个初始化vptr。...用 C 语言实现封装、继承,理解和实现起来比较简单,多态反而会稍微复杂一点,如果打算广泛使用多态,还是推荐转到 C++ 语言上,毕竟这层复杂性被这个语言给封装了,你只需要简单使用就行了。

    79310

    C++继承继承情况下虚函数表分析

    C++三大特性之一多态是基于虚函数实现,而大部分编译器是采用虚函数表来实现虚函数,虚函数表(VTAB)存在于可执行文件只读数据段中,指向VTAB虚表指针(VPTR)是包含在每一个实例当中。...当使用引用或指针调用虚函数时,首先通过VPTR找到VTAB,然后通过偏移量找到虚函数地址并调用。...《深度探索C++对象模型》 一、继承 1 #include 2 #include 3 using namespace std; 4 class A {...这些表按照派生顺序依次排列,如果子类改写了父虚函数,那么就会用子类自己虚函数覆盖虚函数表相应位置,如果子类虚函数,那么就添加到第一个虚函数表末尾。...再简单总结一下 覆盖 隐藏 重载 区别: 覆盖 是C++虚函数实现原理,基虚函数被子类重写,要求函数参数列表相同; 隐藏 是C++名字解析过程,分两种情况,基函数virtual,参数列表不同

    2.7K10

    c++对象内存布局

    首先,它可以去除我们对于所使用语言神秘感,使我们不至于对于编译器干活感到完全不可思议;尤其重要是,它使我们在Debug和使用语言高级特性时候,更多把握。...对于virtual关键字,编译器会自动将指向虚拟表指针(vptr)插入对象内存表示中。通常,虚拟表是在数据段中为每个静态创建,但它也取决于编译器实现。...在虚拟表中,第一个条目指向type_info对象,该对象包含与当前基和其他基DAG(向无环图)相关信息(如果从这些基派生信息)。...,基和数据成员是派生对象。...如果尝试使用任何基指针调用Z方法,则它将使用相应虚拟表进行调用。

    959100
    领券