IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 开发工具 -> 虚函数和虚继承 -> 正文阅读

[开发工具]虚函数和虚继承

  • 虚函数表指针:vfptr -> 指向一个虚函数表,为了解决多态问题。
  • 虚基类指针:vbptr -> 指向一个虚基类表,为了解决类似棱形继承的二义性问题。

虚继承

#include <iostream>

using namespace std;

class Animal
{
public:
    virtual ~Animal() = default;
    int animal;
    virtual void f() { cout << "Animal::f()" << endl; }
    virtual void g() { cout << "Animal::g()" << endl; }

};
//这里添加的virtual对于Sheep和Tuo本身没影响,只对他们的子类有影响。
class Sheep : virtual public Animal
{
public:
    int sheep;
    virtual void f() { cout << "sheep::f()" << endl; }
    virtual void g() { cout << "sheep::g()" << endl; }
    virtual void h() { cout << "sheep::h()" << endl; }
};

class Tuo : virtual public Animal
{
public:
    int tuo;
    virtual void f() { cout << "Tuo::f()" << endl; }
    virtual void g() { cout << "Tuo::g()" << endl; }
    virtual void h() { cout << "Tuo::h()" << endl; }
};

class SheepTuo :public Sheep, public Tuo
{
public:
    int sheep_tuo;
    virtual void f() { cout << "SheepTuo::f()" << endl; }
    virtual void g() { cout << "SheepTuo::g()" << endl; }
    virtual void h() { cout << "SheepTuo::h()" << endl; }
};

int main()
{
    SheepTuo st;
    cout << "sizeof(SheepTuo) is " << sizeof(SheepTuo) << endl;
    return 0;
}

继承关系图
在这里插入图片描述
打开 工具->Visual studio命令提示 工具,cd 到源码所在的路径下,输入cl /d1reportSingleClassLayout"要查看的类名" “文件名”,在这里就是cl /d1reportSingleClassLayoutSheepTuo main.cpp。可以看到当前类内存的结构。(编译后才能查看到内存分布)。

  • Animal的内存布局:
class Animal    size(8):
        +---
 0      | {vfptr}
 4      | animal
        +---

Animal::$vftable@:
        | &Animal_meta
        |  0
 0      | &Animal::{dtor}
 1      | &Animal::f
 2      | &Animal::g

Animal::{dtor} this adjustor: 0
Animal::f this adjustor: 0
Animal::g this adjustor: 0
Animal::__delDtor this adjustor: 0
Animal::__vecDelDtor this adjustor: 0
  • Sheep的内存布局(虚继承会多出一个vbptr,并且自身的类布局会放到最前面,从而会有自身的vfptr)
class Sheep     size(20):
        +---
 0      | {vfptr}
 4      | {vbptr}
 8      | sheep
        +---
        +--- (virtual base Animal)
12      | {vfptr}
16      | animal
        +---

Sheep::$vftable@Sheep@:
        | &Sheep_meta
        |  0
 0      | &Sheep::h

Sheep::$vbtable@:
 0      | -4
 1      | 8 (Sheepd(Sheep+4)Animal)

Sheep::$vftable@Animal@:
        | -12
 0      | &Sheep::{dtor}
 1      | &Sheep::f
 2      | &Sheep::g

Sheep::{dtor} this adjustor: 12
Sheep::f this adjustor: 12
Sheep::g this adjustor: 12
Sheep::h this adjustor: 0
Sheep::__delDtor this adjustor: 12
Sheep::__vecDelDtor this adjustor: 12
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          Animal      12       4       4 0
  • Tuo的内存布局
class Tuo       size(20):
        +---
 0      | {vfptr}
 4      | {vbptr}
 8      | tuo
        +---
        +--- (virtual base Animal)
12      | {vfptr}
16      | animal
        +---

Tuo::$vftable@Tuo@:
        | &Tuo_meta
        |  0
 0      | &Tuo::h

Tuo::$vbtable@:
 0      | -4
 1      | 8 (Tuod(Tuo+4)Animal)

Tuo::$vftable@Animal@:
        | -12
 0      | &Tuo::{dtor}
 1      | &Tuo::f
 2      | &Tuo::g

Tuo::{dtor} this adjustor: 12
Tuo::f this adjustor: 12
Tuo::g this adjustor: 12
Tuo::h this adjustor: 0
Tuo::__delDtor this adjustor: 12
Tuo::__vecDelDtor this adjustor: 12
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          Animal      12       4       4 0
  • SheepTuo的内存布局,由于它的继承并非虚继承,所有自身的类布局放在最后,且没有vbptr.
class SheepTuo  size(36):
        +---
 0      | +--- (base class Sheep)
 0      | | {vfptr}
 4      | | {vbptr}
 8      | | sheep
        | +---
12      | +--- (base class Tuo)
12      | | {vfptr}
16      | | {vbptr}
20      | | tuo
        | +---
24      | sheep_tuo
        +---
        +--- (virtual base Animal)
28      | {vfptr}
32      | animal
        +---

SheepTuo::$vftable@Sheep@:
        | &SheepTuo_meta
        |  0
 0      | &SheepTuo::h

SheepTuo::$vftable@Tuo@:
        | -12
 0      | &thunk: this-=12; goto SheepTuo::h

SheepTuo::$vbtable@Sheep@:
 0      | -4
 1      | 24 (SheepTuod(Sheep+4)Animal)

SheepTuo::$vbtable@Tuo@:
 0      | -4
 1      | 12 (SheepTuod(Tuo+4)Animal)

SheepTuo::$vftable@Animal@:
        | -28
 0      | &SheepTuo::{dtor}
 1      | &SheepTuo::f
 2      | &SheepTuo::g

SheepTuo::f this adjustor: 28
SheepTuo::g this adjustor: 28
SheepTuo::h this adjustor: 0
SheepTuo::{dtor} this adjustor: 28
SheepTuo::__delDtor this adjustor: 28
SheepTuo::__vecDelDtor this adjustor: 28
vbi:       class  offset o.vbptr  o.vbte fVtorDisp
          Animal      28       4       4 0
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

调试窗口看到的布局如下:
在这里插入图片描述

带虚函数的多重继承的内存布局

#include <iostream>

using namespace std;

class Base1
{
public:  //三个虚函数
    virtual void f() { cout << "Base1::f" << endl; }
    virtual void g() { cout << "Base1::g" << endl; }
    virtual void h() { cout << "Base1::h" << endl; }

    int base1;
};

class Base2
{
public:  //三个虚函数
    virtual void f() { cout << "Base2::f" << endl; }
    virtual void g() { cout << "Base2::g" << endl; }
    virtual void h() { cout << "Base2::h" << endl; }

    int base2;
};

class Base3
{
public:  //三个虚函数
    virtual void f() { cout << "Base3::f" << endl; }
    virtual void g() { cout << "Base3::g" << endl; }
    virtual void h() { cout << "Base3::h" << endl; }

    int base3;
};

class Derive :public Base1, public Base2, public Base3
{
public:
    virtual void f() override { cout << "Derive::f" << endl; } //唯一一个覆盖的子类函数
    virtual void g1() { cout << "Derive::g1" << endl; }
    virtual void h1() { cout << "Derive::h1" << endl; }
    virtual void j1() { cout << "Derive::h1" << endl; }

    int derive;
};

int main()
{
    Derive d;
    cout << "sizeof d: " << sizeof(d) << endl;
    return 0;
}

其内存布局如下图所示:
在这里插入图片描述
红框框中的部分表明虚函数表的大小,包含结束标志。

D:\Fzz\src\tectCPP\tectCPP>cl /d1reportSingleClassLayoutDerive main.cpp
用于 x86 的 Microsoft (R) C/C++ 优化编译器 19.16.27045 版
版权所有(C) Microsoft Corporation。保留所有权利。

main.cpp
e:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Tools\MSVC\14.16.27023\include\xlocale(319): warning C4530: 使用了 C++ 异常处理程序,但未启用展开语义。请指定 /EHsc

class Derive    size(28):
        +---
 0      | +--- (base class Base1)
 0      | | {vfptr}
 4      | | base1
        | +---
 8      | +--- (base class Base2)
 8      | | {vfptr}
12      | | base2
        | +---
16      | +--- (base class Base3)
16      | | {vfptr}
20      | | base3
        | +---
24      | derive
        +---

Derive::$vftable@Base1@:
        | &Derive_meta
        |  0
 0      | &Derive::f
 1      | &Base1::g
 2      | &Base1::h
 3      | &Derive::g1
 4      | &Derive::h1
 5      | &Derive::j1

Derive::$vftable@Base2@:
        | -8
 0      | &thunk: this-=8; goto Derive::f
 1      | &Base2::g
 2      | &Base2::h

Derive::$vftable@Base3@:
        | -16
 0      | &thunk: this-=16; goto Derive::f
 1      | &Base3::g
 2      | &Base3::h

Derive::f this adjustor: 0
Derive::g1 this adjustor: 0
Derive::h1 this adjustor: 0
Derive::j1 this adjustor: 0
Microsoft (R) Incremental Linker Version 14.16.27045.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:main.exe
main.obj

参考

图文详解虚继承的实现原理(内存布局分析)

  开发工具 最新文章
Postman接口测试之Mock快速入门
ASCII码空格替换查表_最全ASCII码对照表0-2
如何使用 ssh 建立 socks 代理
Typora配合PicGo阿里云图床配置
SoapUI、Jmeter、Postman三种接口测试工具的
github用相对路径显示图片_GitHub 中 readm
Windows编译g2o及其g2o viewer
解决jupyter notebook无法连接/ jupyter连接
Git恢复到之前版本
VScode常用快捷键
上一篇文章      下一篇文章      查看所有文章
加:2021-10-04 13:02:21  更:2021-10-04 13:04:27 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 0:33:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码