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,不包含虚指针。
相关推荐
晚风(●•σ )2 小时前
C++语言程序设计——06 字符串
开发语言·c++
晚云与城3 小时前
今日分享:C++ -- list 容器
开发语言·c++
兰雪簪轩3 小时前
分布式通信平台测试报告
开发语言·网络·c++·网络协议·测试报告
jingfeng5146 小时前
C++11可变参数模板、emplace系列接口、包装器
开发语言·c++
Kevinhbr6 小时前
CSP-J/S IS COMING
数据结构·c++·算法
蕓晨7 小时前
set的插入和pair的用法
c++·算法
金古圣人7 小时前
hot100 滑动窗口
数据结构·c++·算法·leetcode·哈希算法
蒹葭玉树7 小时前
【C++上岸】C++常见面试题目--算法篇(第二十期)
c++·算法·面试
高山有多高8 小时前
详解文件操作
c语言·开发语言·数据库·c++·算法
狂奔的sherry8 小时前
单例模式(巨通俗易懂)普通单例,懒汉单例的实现和区别,依赖注入......
开发语言·c++·单例模式