C++虚函数在g++中的实现分析

作者: 云计算机网 分类: 云主机 发布时间: 2017-06-15 07:46

本文是我在追查一个诡异core问题的过程中收获的一点心得,把公司项目相关的背景和特定条件去掉后,仅取其中通用的C++虚函数实现部分知识记录于此。

在开始之前,原谅我先借用一张图黑一下C++:

无敌的C++

如果你也在写C++,请一定小心hellip;至少,你要先有所了解: 当你在写虚函数的时候,g++在写什么?

先写个例子

为了探索C++虚函数的实现,我们首先编写几个用来测试的类,代码如下:

C++

#include lt;iostreamgt;

using namespace std;

class Base1
{
public:
    virtual void f() {
        cout lt;lt; "Base1::f()" lt;lt; endl;
    }
};

class Base2
{
public:
    virtual void g() {
        cout lt;lt; "Base2::g()" lt;lt; endl;
    }
};

class Derived : public Base1, public Base2
{
public:
    virtual void f() {
        cout lt;lt; "Derived::f()" lt;lt; endl;
    }

    virtual void g() {
        cout lt;lt; "Derived::g()" lt;lt; endl;
    }

    virtual void h() {
        cout lt;lt; "Derived::h()" lt;lt; endl;
    }
};

int main(int argc, char *argv[])
{
    Derived ins;
    Base1 amp;b1 = ins;
    Base2 amp;b2 = ins;
    Derived amp;d = ins;

    b1.f();
    b2.g();
    d.f();
    d.g();
    d.h();
}

C++虚函数在g++中的实现分析

代码采用了多继承,是为了更多的分析出g++的实现本质,用UML简单的画一下继承关系:

示例代码UML图

代码的输出结果和预期的一致,C++实现了虚函数覆盖功能,代码输出如下:

Derived::f()
Derived::g()
Derived::f()
Derived::g()
Derived::h()
开始分析!

我写这篇文章的重点是尝试解释g++编译在底层是如何实现虚函数覆盖和动态绑定的,因此我假定你已经明白基本的虚函数概念以及虚函数表(vtbl)和虚函数表指针(vptr)的概念和在继承实现中所承担的作用,如果你还不清楚这些概念,建议你在继续阅读下面的分析前先补习一下相关知识,https://www.linuxidc.com/Linux/2015-07/119662.htm。

通过本文,我将尝试解答下面这三个问题:

    g++如何实现虚函数的动态绑定? vtbl在何时被创建?vptr又是在何时被初始化? 在Linux中运行的C++程序虚拟存储器中,vptr、vtbl存放在虚拟存储的什么位置?

首先是第一个问题:

g++如何实现虚函数的动态绑定?

这个问题乍看简单,大家都知道是通过vptr和vtbl实现的,那就让我们刨根问底的看一看,g++是如何利用vptr和vtbl实现的。

第一步,使用 -fdump-class-hierarchy 参数导出g++生成的类内存结构:

Vtable for Base1
Base1::_ZTV5Base1: 3u entries
0     (int (*)(...))0
4     (int (*)(...))(amp; _ZTI5Base1)
8     Base1::f

Class Base1
   size=4 align=4
   base size=4 base align=4
Base1 (0xb6acb438) 0 nearly-empty
    vptr=((amp; Base1::_ZTV5Base1) + 8u)

Vtable for Base2
Base2::_ZTV5Base2: 3u entries
0     (int (*)(...))0
4     (int (*)(...))(amp; _ZTI5Base2)
8     Base2::g

Class Base2
   size=4 align=4
   base size=4 base align=4
Base2 (0xb6acb474) 0 nearly-empty
    vptr=((amp; Base2::_ZTV5Base2) + 8u)

Vtable for Derived
Derived::_ZTV7Derived: 8u entries
0     (int (*)(...))0
4     (int (*)(...))(amp; _ZTI7Derived)
8     Derived::f
12    Derived::g
16    Derived::h
20    (int (*)(...))-0x000000004
24    (int (*)(...))(amp; _ZTI7Derived)
28    Derived::_ZThn4_N7Derived1gEv

Class Derived
   size=8 align=4
   base size=8 base align=4
Derived (0xb6b12780) 0
    vptr=((amp; Derived::_ZTV7Derived) + 8u)
  Base1 (0xb6acb4b0) 0 nearly-empty
      primary-for Derived (0xb6b12780)
  Base2 (0xb6acb4ec) 4 nearly-empty
      vptr=((amp; Derived::_ZTV7Derived) + 28u) 
  • 微软在将要发布的Windows 10创造者更新当中提供了诸多新功能,其中就包括一个虚拟触摸板。

    在最新的Insider Windows 10预览版本14965中,我们看到微软为平板电脑设备添加了虚拟触摸板,以便在必要时充当鼠标使用。

    用户可以长按任务栏,并从选项中选择触摸板来启用此项功能。

    然后,用户可以导航到设置gt;设备gt;触摸板,更改用户物理触摸板和新的虚拟触摸板设置。

    该功能让用户在设备连接到第二块显示屏,并且没有鼠标可用的情况下,创建虚拟触摸板,来代替物理鼠标完成光标移动和左右键点击功能。

  • 相关推荐:

  • Windows10“创造者”更新将
  • 新之洲网络香港虚拟主机
  • 思科调查表明增加虚拟助
  • Netsh命令虚拟WIFI无线教程
  • 关于虚拟网卡采集无线网
  • 虚拟主机FTP无法上传文件
  • Windows7虚拟WIFI介绍
  • 物理内存与虚拟内存区别
  • 设定虚拟内存的误区
  • 什么是虚拟运营商
  • 网站内容禁止违规转载,转载授权联系中国云计算网