单类单继承虚函数下的数据成员布局
- 1. 单一类带虚函数的数据成员布局
- 2. 单一继承父类带虚函数的数据成员布局
- 3. 单一继承父类不带虚函数的数据成员布局
在单类单继承的情况下,虚函数的存在会影响数据成员的布局。虚函数表(vtable)和虚指针(vptr)是实现多态性的重要机制。
1. 单一类带虚函数的数据成员布局
当一个类包含虚函数时,编译器会为该类生成一个虚函数表(vtable),并在每个对象中添加一个指向该表的指针(vptr)。虚指针通常是对象内存布局中的第一个成员。
示例代码:
#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通常是对象内存布局中的第一个成员,紧接着是var1和var2。
2. 单一继承父类带虚函数的数据成员布局
当子类继承一个带有虚函数的父类时,子类对象的内存布局包含父类的虚指针和数据成员,以及子类自己的数据成员。
示例代码:
#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. 单一继承父类不带虚函数的数据成员布局
当子类继承一个不带虚函数的父类时,子类对象的内存布局仅包含父类和子类的成员变量,不包含虚指针。
示例代码:
#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,不包含虚指针。
