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,不包含虚指针。
相关推荐
我是谁??15 分钟前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
发霉的闲鱼1 小时前
MFC 重写了listControl类(类名为A),并把双击事件的处理函数定义在A中,主窗口如何接收表格是否被双击
c++·mfc
小c君tt1 小时前
MFC中Excel的导入以及使用步骤
c++·excel·mfc
xiaoxiao涛1 小时前
协程6 --- HOOK
c++·协程
羊小猪~~3 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
脉牛杂德4 小时前
多项式加法——C语言
数据结构·c++·算法
legend_jz4 小时前
STL--哈希
c++·算法·哈希算法
CSUC4 小时前
【C++】父类参数有默认值时子类构造函数列表中可以省略该参数
c++
Vanranrr4 小时前
C++ QT
java·c++·qt
鸿儒5174 小时前
C++ lambda 匿名函数
开发语言·c++