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,不包含虚指针。
相关推荐
LyaJpunov9 天前
深入理解 C++ volatile 与 atomic:五大用法解析 + 六大高频考点
c++·面试·volatile·atomic
小灰灰搞电子9 天前
Qt PyQt与PySide技术-C++库的Python绑定
c++·qt·pyqt
时空自由民.9 天前
C++ 不同线程之间传值
开发语言·c++·算法
Ray_19979 天前
C++二级指针的用法指向指针的指针(多级间接寻址)
开发语言·jvm·c++
双叶8369 天前
(C语言)Map数组的实现(数据结构)(链表)(指针)
c语言·数据结构·c++·算法·链表·哈希算法
Jay_5159 天前
C++ STL 模板详解:由浅入深掌握标准模板库
c++·学习·stl
Cyrus_柯9 天前
C++(面向对象编程——继承)
开发语言·c++·算法·面向对象
Echo``9 天前
12.OpenCV—基础入门
开发语言·c++·人工智能·qt·opencv·计算机视觉
十秒耿直拆包选手9 天前
C++:动态库相关文件
c++
小L~~~9 天前
C++网络编程入门学习(五)-- CMake 学习笔记
linux·c++