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,不包含虚指针。
相关推荐
qwehjk200816 分钟前
分布式计算C++库
开发语言·c++·算法
m0_7167652316 分钟前
C++提高编程--仿函数、常用遍历算法(for_each、transform)详解
java·开发语言·c++·经验分享·算法·青少年编程·visual studio
寻寻觅觅☆22 分钟前
东华OJ-基础题-59-倒数数列(C++)
开发语言·c++·算法
Trouvaille ~26 分钟前
【优选算法篇】BFS 解决最短路——寻找最优路径的真谛
c++·算法·leetcode·面试·蓝桥杯·宽度优先·最短路问题
CoderCodingNo39 分钟前
【CSP】CSP-J 2025真题 | 多边形 luogu-P14360 (相当于GESP六级水平)
开发语言·c++·算法
Magic--1 小时前
【LeetCode 27. 移除元素】C++ 范围 for 极简实现与原理解析
c++·算法·leetcode
旖-旎1 小时前
位运算(只出现一次的数字|||)(5)
c++·算法·leetcode·位运算
kyle~1 小时前
ROS2---客户端服务(rclcpp::Client)
c++·物联网·机器人·ros2
轻口味1 小时前
HarmonyOS 6 自定义人脸识别模型8:MindSpore Lite框架介绍与使用
c++·华为·ai·harmonyos
IdahoFalls1 小时前
QT-Windows Kits-版本问题:【“_mm_loadu_si64”: 找不到标识符】解决方案[NEW]
开发语言·c++·windows·qt·算法·visual studio