C++ 数据语义学——单类单继承虚函数下的数据成员布局

单类单继承虚函数下的数据成员布局

      • [1. 单一类带虚函数的数据成员布局](#1. 单一类带虚函数的数据成员布局)
      • [2. 单一继承父类带虚函数的数据成员布局](#2. 单一继承父类带虚函数的数据成员布局)
      • [3. 单一继承父类不带虚函数的数据成员布局](#3. 单一继承父类不带虚函数的数据成员布局)

在单类单继承的情况下,虚函数的存在会影响数据成员的布局。虚函数表(vtable)和虚指针(vptr)是实现多态性的重要机制。

1. 单一类带虚函数的数据成员布局

当一个类包含虚函数时,编译器会为该类生成一个虚函数表(vtable),并在每个对象中添加一个指向该表的指针(vptr)。虚指针通常是对象内存布局中的第一个成员。

示例代码:

cpp 复制代码
#include <iostream>

class MyClass {
public:
    int var1;
    double var2;

    virtual void myVirtualFunction() {
        std::cout << "MyClass virtual function" << std::endl;
    }
};

int main() {
    MyClass obj;

    std::cout << "Address of obj: " << &obj << std::endl;
    std::cout << "Address of vptr: " << reinterpret_cast<void**>(&obj) << std::endl;
    std::cout << "Address of var1: " << &obj.var1 << std::endl;
    std::cout << "Address of var2: " << &obj.var2 << std::endl;

    return 0;
}

运行结果(地址可能因系统和编译器不同而有所不同):

复制代码
Address of obj: 0x71fe30
Address of vptr: 0x71fe30
Address of var1: 0x71fe38
Address of var2: 0x71fe40

在上面的代码中:

  • MyClass 包含一个虚函数 myVirtualFunction
  • obj 对象的内存布局中包含一个虚指针 vptr,指向虚函数表。
  • vptr 通常是对象内存布局中的第一个成员,紧接着是 var1var2

2. 单一继承父类带虚函数的数据成员布局

当子类继承一个带有虚函数的父类时,子类对象的内存布局包含父类的虚指针和数据成员,以及子类自己的数据成员。

示例代码:

cpp 复制代码
#include <iostream>

class Base {
public:
    int baseVar;

    virtual void baseVirtualFunction() {
        std::cout << "Base virtual function" << std::endl;
    }
};

class Derived : public Base {
public:
    char derivedVar;

    void baseVirtualFunction() override {
        std::cout << "Derived override function" << std::endl;
    }
};

int main() {
    Derived obj;

    std::cout << "Address of obj: " << &obj << std::endl;
    std::cout << "Address of vptr: " << reinterpret_cast<void**>(&obj) << std::endl;
    std::cout << "Address of baseVar: " << &obj.baseVar << std::endl;
    std::cout << "Address of derivedVar: " << static_cast<void*>(&obj.derivedVar) << std::endl;

    return 0;
}

运行结果(地址可能因系统和编译器不同而有所不同):

复制代码
Address of obj: 0x71fe40
Address of vptr: 0x71fe40
Address of baseVar: 0x71fe48
Address of derivedVar: 0x71fe4c

在上面的代码中:

  • Base 类包含一个虚函数 baseVirtualFunction
  • Derived 类继承自 Base 类,并重写了 baseVirtualFunction
  • Derived 类对象 obj 的内存布局包含父类的虚指针 vptr 和数据成员 baseVar,以及子类的成员 derivedVar

3. 单一继承父类不带虚函数的数据成员布局

当子类继承一个不带虚函数的父类时,子类对象的内存布局仅包含父类和子类的成员变量,不包含虚指针。

示例代码:

cpp 复制代码
#include <iostream>

class Base {
public:
    int baseVar;
};

class Derived : public Base {
public:
    char derivedVar;
};

int main() {
    Derived obj;

    std::cout << "Address of obj: " << &obj << std::endl;
    std::cout << "Address of baseVar: " << &obj.baseVar << std::endl;
    std::cout << "Address of derivedVar: " << static_cast<void*>(&obj.derivedVar) << std::endl;

    return 0;
}

运行结果(地址可能因系统和编译器不同而有所不同):

复制代码
Address of obj: 0x71fe48
Address of baseVar: 0x71fe48
Address of derivedVar: 0x71fe4c

在上面的代码中:

  • Base 类不包含虚函数。
  • Derived 类继承自 Base 类。
  • Derived 类对象 obj 的内存布局仅包含父类的成员 baseVar 和子类的成员 derivedVar,不包含虚指针。
相关推荐
肆忆_7 小时前
# 用 5 个问题学懂 C++ 虚函数(入门级)
c++
不想写代码的星星11 小时前
虚函数表:C++ 多态背后的那个男人
c++
端平入洛2 天前
delete又未完全delete
c++
端平入洛3 天前
auto有时不auto
c++
哇哈哈20214 天前
信号量和信号
linux·c++
多恩Stone4 天前
【C++入门扫盲1】C++ 与 Python:类型、编译器/解释器与 CPU 的关系
开发语言·c++·人工智能·python·算法·3d·aigc
蜡笔小马4 天前
21.Boost.Geometry disjoint、distance、envelope、equals、expand和for_each算法接口详解
c++·算法·boost
超级大福宝4 天前
N皇后问题:经典回溯算法的一些分析
数据结构·c++·算法·leetcode
weiabc4 天前
printf(“%lf“, ys) 和 cout << ys 输出的浮点数格式存在细微差异
数据结构·c++·算法
问好眼4 天前
《算法竞赛进阶指南》0x01 位运算-3.64位整数乘法
c++·算法·位运算·信息学奥赛