单类单继承虚函数下的数据成员布局
-
-
- [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
通常是对象内存布局中的第一个成员,紧接着是var1
和var2
。
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
,不包含虚指针。