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

vptr和vtable是从基类继承的吗?

vptr和vtable是C++中实现多态性的机制,它们通常与虚函数(virtual function)相关联。vptr是一个指向虚函数表(vtable)的指针,而vtable是一个存储了虚函数地址的表。

在C++中,当一个类声明了虚函数时,编译器会为该类生成一个隐藏的vptr成员变量,并在对象的内存布局中添加一个指向虚函数表的指针。这个虚函数表是一个由编译器生成的静态表,其中存储了该类及其所有派生类的虚函数地址。

当一个对象被创建时,其vptr会被初始化指向相应的虚函数表。当通过基类指针或引用调用虚函数时,实际调用的是根据vptr指向的虚函数表中对应的函数。

vptr和vtable是通过继承关系传递的,即如果一个派生类继承了一个基类,它也会继承基类的vptr和vtable。这意味着派生类对象的vptr指向的是派生类的虚函数表,而不是基类的虚函数表。因此,vptr和vtable是从基类继承的。

vptr和vtable的存在使得在面向对象编程中实现多态性成为可能。通过使用虚函数和vptr/vtable机制,可以在运行时动态地确定调用哪个派生类的虚函数,实现了多态性的特性。

腾讯云相关产品和产品介绍链接地址:

  • 腾讯云服务器(CVM):https://cloud.tencent.com/product/cvm
  • 腾讯云数据库(TencentDB):https://cloud.tencent.com/product/cdb
  • 腾讯云人工智能(AI):https://cloud.tencent.com/product/ai
  • 腾讯云物联网(IoT):https://cloud.tencent.com/product/iotexplorer
  • 腾讯云移动开发(移动推送、移动分析等):https://cloud.tencent.com/product/mobile
  • 腾讯云存储(对象存储、文件存储等):https://cloud.tencent.com/product/cos
  • 腾讯云区块链(腾讯区块链服务):https://cloud.tencent.com/product/tbaas
  • 腾讯云元宇宙(腾讯云元宇宙解决方案):https://cloud.tencent.com/solution/virtual-universe
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

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

再说回内存布局,在非虚继承时候,前面也说了按照顺序存储,那么虚继承也是这样?...有人会说,上面不是说虚继承会重新生成虚表指针,但这里B虚继承A,但是D继承时候是非虚继承,所以D并不会重新生成虚表指针,但此处BC应该重新生产虚表指针,gdb查看却没有,我一开始也很疑惑...、C、D这三个,它是按照顺序来存储,对于A与我们上一章虚继承得出结果一样,虚虚表指针成员变量放在一块内存最后面的。...,如果派生有同样虚函数,那就覆盖虚表中同名函数,如果派生独有的虚函数,那就追加在虚函数表后面; 一个派生继承于一个有虚函数且没有成员变量,则派生也不会生成它自己虚表指针虚函数表...,此时内存布局首先是虚表指针,然后派生成员变量,与第4点区别不大; 一个派生继承于一个有虚函数且有成员变量,此时派生会重新生成它自己虚表指针虚函数表,内存布局则是派生虚表指针成员变量在前

64220

C# 继承 派生初始化C# 多重继承

C# 继承 继承面向对象程序设计中最重要概念之一。继承允许我们根据一个来定义另一个,这使得创建和维护应用程序变得更容易。同时也有利于重用代码节省开发时间。...当创建一个时,程序员不需要完全重新编写新数据成员成员函数,只需要设计一个新继承了已有的成员即可。这个已有的被称为,这个新被称为派生。...派生 一个可以派生自多个或接口,这意味着它可以多个或接口继承数据函数。...C# 中创建派生语法如下: class { ... } class : { ... } 假如一个Shape,一个派生Rectangle...派生继承成员变量成员方法。

4.4K20

VCGCC成员函数指针实现研究(三)

*ptr)(); return 0; } VC虚继承成员函数指针实现 因为兼容虚继承非虚继承,所以赋值部分汇编一样。这里就不贴了。关键在于执行期它是怎么找到虚。...但是直接调用c.info()调用第一个虚函数指针(c.*vptr2)()this都是虚foo_l指针,但是(c.*vptr1)()this指针却是虚foo_a指针。...image.png 图十八:GCC多重虚继承直接函数调用 image.png 图十九:GCC多重虚继承空虚函数指针调用 首先,GCC直接调用调用空虚成员函数时,cx直接传入子类地址...image.png 图二十:GCC多重虚继承非空虚函数指针调用 image.png 图二十一:GCC多重虚继承非空虚函数指针调用偏移调整 多重继承做法类似:先给增加地址偏移...你可以试下把子类成员函数指针转换为成员函数指针,如果这个不是子类第一父,转换过程必然会导致修正这个offset值。 (考你个问题:子类引用转父引用是左值?)。

79610

再探虚函数

(这句话刚开始还真没反应过来,也是啊,都不能初始化对象了,还怎么去调用方法啊) ---- Q3:抽象派生对象可以调用方法?...只有在析构函数定义为虚函数时,调用操作符delete销毁指向对象指针时,才能准确调用派生析构函数(该级向上按序调用虚函数),才能准确销毁数据。...---- Q7:构造函数析构函数可以调用虚函数,为什么?...虚函数依靠vptrvtable来处理。...vptr一个指针,在构造函数中创建生成,并且只能用this指针来访问它,因为它是一个成员,并且vptr指向保存虚函数地址vtable.对于静态成员函数,它没有this指针,所以无法访问vptr

85620

深入浅出C++虚函数vptrvtable

深入浅出C++虚函数vptrvtable 1.基础理论 为了实现虚函数,C ++使用一种称为虚拟表特殊形式后期绑定。该虚拟表用于解决在动态/后期绑定方式函数调用函数查找表。...首先,每个使用虚函数(或者使用虚函数派生)都有自己虚拟表。该表只是编译器在编译时设置静态数组。虚拟表包含可由对象调用每个虚函数一个条目。...与this指针不同,this指针实际上编译器用来解析自引用函数参数,vptr一个真正指针。 因此,它使每个对象分配大一个指针大小。这也意味着vptr由派生继承,这很重要。.../** * @file vptr1.cpp * @brief C++虚函数vptrvtable * 编译:g++ -g -o vptr vptr1.cpp -std=c++11 * @author...); cout<<"引用指向实例并调用虚函数"<<endl; p.fun1(); // 手动查找vptr vtable Fun f1 = getAddr(pt

4K30

抽象为什么不能被实例化?

其次,继承多态思想角度而言,抽象目的建立一个公共接口,建立公共接口唯一原因它能对于每个不同子类有不同表示。...它建立一个基本格式,用来确定什么对于所有派生公共——除此之外,别无用途。抽象仅仅表示接口,不表示特例实现,因此,实例化一个抽象对象,总是没有意义。...第三,编译器设计实现上来看,如果想要禁止用户实例化抽象,可以在抽象所有虚函数里,打印出错信息,以提示用户不能实例化抽象。...实现上,通过在虚函数结尾处加上"=0"来声明纯虚函数: virtual void func() = 0; 虚函数与多态原理在于,带有虚函数及其派生,其对象内部会有一个指向VTABLE指针,即vptr...因此,只要有一个函数在中被声明为纯虚函数,则VTABLE就是不完全。 如果一个VTABLE不完全,当某人试图创建这个对象时,编译器做什么呢?它不能安全地创建一个纯抽象对象。

45920

C++ 多态实现机制

i vptr 指向虚函数表(Vtable), 虚函数表中存储该类中所有的 virtual function 指针, 也就是说, 每个只有一张虚函数表, 可以验证一下这件事 Animal a,...需要注意一点, 派生虚函数表结构一致, 其中析构函数 eat() 自己, bark() 沿用了 Animal (析构函数编译器自动制造一个)....对象没有发生任何变化, 仅仅是让一个指针指向了派生对象. 如果把派生对象赋值给对象会发生什么?...Animal a; Dog b; a = b; a.eat(); 输出如下: Animal::eat() 这叫做sliced off, 只有继承部分会被拷贝给 a, 其余部分就被 “切掉了”...同时可以看到, 最后打印了一个奇怪值, 因为 Dog 中新增了一个成员变量 tail (可以看到尽管 tail private 也并非没有办法去访问甚至修改), 而在 Animal 中不存在

66140

C++面试题

当一个构造函数被调用时,它做首要事情之一初始化它VPTR。因此,它只能知道它是“当前”,而完全忽视这个对象后面是否还有继承者。...当编译器为这个构造函数产生代码时,它是为这个构造函数产生代码——既不是为,也不是为它派生(因为不知道谁继承它)。所以它使用VPTR必须对于这个VTABLE。...VPTR状态由被最后调用构造函数确定。这就是为什么构造函数调用是到更加派生顺序另一个理由。...而子类析构函数具有析构掉职责,所以不会造成内存泄漏。而并不知道自己子类。 4. 构造函数析构函数能抛出异常? 不能。 5. 多继承存在什么问题?如何消除多继承二义性?...在继承时,之间或与派生之间发生成员同名时,将出现对成员访问不确定性,即同名二义性。

1.7K42

从零开始学C++之虚继承虚函数对C++对象内存模型造成影响(对象大小)

输出地址表成员数据可以画出对象内存模型图: virtual base table  本类地址与虚表指针地址差 虚地址与虚表指针地址差 virtual base...如果派生多个继承或者有多个继承分支(所有根开始算起),而其中若干个继承分支上出现了多态,则派生将从这些分支中每个分支上继承一个vptr,编译器也将为它生成多个vtable,有几个vptr...就生成几个vtable(每个vptr分别指向其中一个),分别与它多态对应。...输出表成员数据虚函数体可以画出对象内存模型图: ? 上图中vfdd 出现位置跟继承顺序有关,如果DD先继承B2,那么它将跟在vfb2 下面。...注意:如果没有虚继承,则虚函数表会合并,一个只会存在一个虚函数表一个虚函数表指针(同个对象共享),当然也不会有虚表指针存在。

99000

深度解读《深度探索C++对象模型》之C++虚函数实现分析(一)

还得看Object具体定义,它可能独立,也有可能经过多重继承,或者继承中有一个虚。...接下来内容中将详细分析虚函数实现细节,包括单一继承、多重继承继承情况。多态C++中最重要特性之一,也是组成面向对象编程范式基石,虚函数则是为多态而生。那么何为多态?...其实这个完整表叫做虚表,它包含了虚函数表、RTTI信息继承相关信息,ClangGcc编译器把它们合在一起了,其它编译器可能分开。...,虚函数表中内容主要来自于三方面:改写中对应虚函数,用自己实现虚函数地址写入到对应表格中位置;继承而来虚函数,直接拷贝虚函数地址添加到虚函数表中;新增虚函数,中没有,...子类虚函数表会增加一行容纳新条目;子类使用各自虚函数表,互不干扰,即使子类中没有改写虚函数,也没有新增虚函数,编译器也会为子类新建一个虚函数表,内容中拷贝过来,内容完全一样。

21320

再议内存布局

你好,我雨乐! 在上一篇文章C++:技术角度聊聊RTTI中聊到了虚函数表,以及内部部分布局。...Base1class Base2中成员变量也是无关,因此间也不具有包含关系;这使得class Base1class Base2在class Derived中必须要处于两个不相交区域中,同时需要有两个虚指针分别对它们虚函数表索引...因为多重继承,所以编译器将先继承那个认为(primary base) ,因此Derived就是class Base1。...在多继承中,当最左边中没有虚函数时候,编译器会将第一个有虚函数移到对象开头,这样对象开头总是有vptr。...::_ZThn16_N7Derived2f2Ev 偏移值为-16,因为多重继承,所以class Base1class Base2指针或者引用都可以指向class Derived对象,那么又是如何调用正确成员函数呢

34840

轻松搞定面试中“虚”

包括:虚函数,纯虚函数,虚,虚继承... 1.什么虚函数,有什么作用? 在用virtual声明成员函数为虚函数。这样就可以在派生中重新定义此函数,为它赋予新功能,并能方便地被调用。...虚函数作用是允许在派生中重新定义与类同名函数,并且可以通过指针或引用来访问派生同名函数,达到多态目的。 2.什么纯虚函数,什么纯虚,有什么作用?...虚拟继承与普通继承不同,虚拟继承可以防止出现diamond继承时,一个派生中同时出现了两个子对象。也就是说,为了保证这一点,在虚拟继承情况下,子对象布局不同于普通继承。...为实现动态联编,编译器为每个包含虚函数创建一个表,称为vtable,在vtable中,编译器放置了特定虚函数地址,在每个带有虚函数中编译器会秘密地设置一个虚函数表指针,称为vptr,指向对象...vtable,通过指针做虚函数调用时,也就是多态调用时,编译器静态地插入取得这个vptr,并在vtable表种查找函数地址代码,这样就能调用正确函数。

66020

C++基础-多态

在编码时,我们将不同类型(具有继承层次关系派生)对象视为对象进行统一处理,不必关注各派生细节,在运行时,将会通过相应机制执行各对象所属方法。...如果不将析构函数声明为虚函数,那么如果一个函数形参指针,实参指向堆内存派生指针时,函数返回时作为实参派生指针将被当作指针进行析构,这会导致资源释放不完全内存泄漏;要避免这一问题,...纯虚函数抽象 在 C++ 中,包含纯虚函数抽象。抽象用于定义接口,在派生中实现接口,这样可以实现接口与实现分离。抽象不能被实例化。...可见使用虚继承可以解决多继承菱形问题,确保 在继承层次结构中,继承多个同一个派生而来时,如果这些没有采用虚继承,将导致二义性。...<< endl; } }; Tuna 可以被继承,但 Swim() 函数不能派生实现覆盖。 8. 可将复制构造函数声明为虚函数 答案不可以。

83920

C++纯虚函数 virtual =0

我试图从一个抽象角度描述一下,回头再结合那个画图例子,也许你就更容易理解。     在面向对象编程中,首先会针对数据进行抽象(确定继承(确定派生),构成层次。...在创建实例时候,编译器还会在每个实例内存布局中增加一个vptr字段,该字段指向本类VTABLE。...a) {     (a->vptr[1])(); }     因为派生foo()函数具有相同VTABLE索引,而他们vptr又指向不同VTABLE,因此通过这样方法可以在运行时刻决定调用哪个...}; class C: public B  // B继承,不是A继承! { public:     void foo();    // 也没有virtual关键字!...设计角度讲,出现在虚函数接口,出现在派生虚函数接口具体实现。通过这样方法,就可以将对象行为抽象化。

1.5K40

二进制学习系列-堆溢出

之后成员变量内存数据。 对于子类,最开始内存数据记录着父对象拷贝(包括父虚函数表指针成员变量)。 之后子类自己成员变量数据。 ? 单继承,无虚函数重载: ?...总结 如果一个中有虚函数,那么就会建立一张虚函数表vtable,子类继承vtable,若,父vtable中私有(private)虚函数,则子类vtable中同样有该私有(private)虚函数地址...vptr每个对象都会有一个,而vptable每个有一个,vptr指向vtable,一个中就算有多个虚函数,也只有一个vptr;做多重继承时候,继承了多个父,就会有多个vptr 详情知识请移步:...快速浏览一遍过后我们可以观察到主要HumanMan、Woman三个,Human,其余继承子类,并且两个子类都重写了父introduce函数,我们还注意到了父getshell...我们可以大致推测出v12v13同一个vptr指针,偏移+8后刚好getshell地址+8后introduce函数地址,所以我们可以开始利用,把vtable地址-8,即把vptr指针指向地址

89441

【C++】多态 ⑦ ( 多态机制实现原理 | 虚函数表概念 | 虚函数表工作机制 | vptr 指针 | 虚函数表运行时机制 | 虚函数与动态联编 )

一、多态原理 1、多态成立三个条件 " 多态 " 实现需要满足以下三个条件 : 首先 , 要有 继承关系 ; 然后 , 父函数需要有 virtual 关键字修饰 , 子类重写该 " 虚函数 "...; 最后 , 父指针 或 父引用 指向 子类对象 ; 满足 ① 继承 , ② 虚函数重写 , ③ 父指针/引用指向子类对象 三个条件 , 即可实现多态 ; 2、虚函数表概念 " 多态 " 机制..., 由 " 虚函数表 " 实现 ; " 虚函数表 " , 英文名称为 " Virtual Function Table " , 简称 Vtable ; C++ 编译器 通过将 虚函数指针 放入 ...虚函数 , 则 该类 每个对象 中 , 都有一个 指向 虚函数表 vptr 指针 ; 虚函数表 存储 虚函数指针 : " 虚函数表 " 存储 " 成员函数指针 " 数据结构 , 一个...Parent 父 还是 Child 子类 , 而是根据对象中 vptr 指针 指向 虚函数表 调用 对应 虚函数 ; 父对象 子类对象 中 都有一个 vptr 指针 成员变量 , 当调用

28130

本周阅读:深度探索C++对象模型

;(普通成员变量就不会了) 情况2 如果一个没有任何构造函数,但是该类继承自含有默认构造函数,该有nontrivial default constructor,此时编译器会为该类合成一个默认构造函数...;(普通就不会了) 情况3 带有虚函数(添加额外信息) 情况4 带有虚构造函数,有成员构造函数,还有自己构造函数,哪有优先执行(混乱)?...(我们一定不能拷贝右端对象vptr地址, 因 为它可能一个继承对象) * 当继承自一个虚(不论此有没有拷贝操作)时 https://github.com/wangcy6/weekly...the vptr Initialization 第5.2章节] 补充内容 错误理解3 vptr在构造函数内初始化, 正确理解: 在父构造函数之后,子类构造函数之前(因为子类构造函数可能执virtual...Initialization The Semantics of the vptr Initialization 构造函数执行算法通常如下: 在派生构造函数中, 所有虚以及上一层构造函数会被调用

77320

派生中虚函数非虚函数继承效果

,在编译阶段就确定好被谁调用,所以他只认哪个指针指向自己,这里Animal指针指向,所以他就调用Animal里面的,普通函数为子类提供“强制实现”,也就是只要是父指针调用普通函数,那就是父普通函数...子类可以重写父虚函数实现子类特殊化。 2、纯虚函数:   C++中包含纯虚函数,被称为“抽象”。抽象不能使用new出对象,只有实现了这个纯虚函数子类才能new出对象。   ...C++中纯虚函数更像是“只提供申明,没有实现”,对子类约束,“接口继承”。   C++中纯虚函数也是一种“运行时多态”。...3、普通函数:   普通函数静态编译,没有运行时多态,只会根据指针或引用“字面值”对象,调用自己普通函数。   普通函数为子类提供“强制实现”。   ...因此,在继承关系中,子类不应该重写父普通函数,因为函数调用至于对象字面值有关。 参考链接

7210
领券