C++对象的内存分布和虚函数表是C++中非常重要的一个知识点。在本篇攻略中,我将详细讲解这个知识点,主要包括以下内容:
-
C++对象的内存分布
-
虚函数表的概念
-
虚函数表的实现
-
示例说明
一、C++对象的内存分布
C++对象在内存中的分布一般包括以下几个部分:
-
对象头部分:一般包括虚函数表指针和类型信息指针;
-
对象的成员变量部分:对象的所有成员变量都存放在这里;
-
对象的函数部分:对象的非虚函数也会被存放在这里。
总的来说,一个C++对象的内存分布可以用下面的图示表示:
------------------
| VTablePtr | ---> 虚函数表指针
------------------
| TypeInfoPtr | ---> 类型信息指针
------------------
| MemberVar1 |
| MemberVar2 |
| ... | ---> 成员变量
| MemberVarN |
------------------
| Non-Virtual |
| Func1 |
| Func2 |
| ... | ---> 非虚函数
| FuncN |
------------------
二、虚函数表的概念
虚函数表是C++中用于实现多态的一种机制。每个包含虚函数的类都有一个对应的虚函数表,虚函数表中存放着这个类的虚函数的地址。虚函数表是一个指向函数地址数组的指针,数组中存放的是函数地址,每个位置对应一个虚函数。
子类继承了父类中的虚函数,并且可以重写虚函数,如果子类重写了虚函数,则会更新虚函数表中相应的函数地址。
三、虚函数表的实现
虚函数表的实现是由编译器自动完成的,编译器会在类中添加一个隐藏的虚函数表指针成员变量(即上面提到的对象头部分中的虚函数表指针),并且在类的构造函数中初始化这个指针,指向该类的虚函数表。虚函数表指针是一个指向虚函数表的指针。
虚函数表的实现方式可以用下面的示例说明:
#include <iostream>
using namespace std;
class A {
public:
virtual void foo() { cout << "A::foo()" << endl; }
};
class B : public A {
public:
virtual void foo() { cout << "B::foo()" << endl; }
virtual void bar() { cout << "B::bar()" << endl; }
};
int main() {
B b;
long long* pVTable = (long long*)(*(long long*)&b); // 取出b的虚函数表指针
long long* pFunc = (long long*)*(pVTable + 1); // 取出B::foo()的地址
void (*f)() = (void (*)())pFunc; // 转换为函数指针
f(); // 调用B::foo()
return 0;
}
对上述代码的解释:
-
程序中定义了两个类
A
和B
,B
是A
的子类。 -
B
类覆写了父类的虚函数foo()
,并且增加了一个新的虚函数bar()
。 -
在程序中定义了一个
B
类的对象b
。 -
通过
*(long long*)&b
的方式,获得了b
的虚函数表指针。 -
对于
B
类中的foo()
函数,它是虚函数,它的函数地址存储在虚函数表中,通过*(pVTable + 1)
的方式,取出了B::foo()
的地址。 -
将
B::foo()
的地址转化成函数指针,并且通过指针调用它。
四、示例说明
在下面的示例中,我们定义了一个简单的图形类Shape
,它有两个成员变量x
和y
,以及一个纯虚函数area()
。由于area()
是一个纯虚函数,所以Shape
类是一个抽象类,不能直接实例化。
我们又定义了两个派生类Rectangle
和Circle
,它们都继承了Shape
类,重载了area()
函数,分别实现了矩形和圆的面积计算。
#include <iostream>
using namespace std;
class Shape {
public:
Shape(int x, int y) : x_(x), y_(y) {}
virtual ~Shape() {}
virtual double area() = 0;
protected:
int x_, y_;
};
class Rectangle : public Shape {
public:
Rectangle(int x, int y, int w, int h) : Shape(x, y), w_(w), h_(h) {}
virtual double area() override { return w_ * h_; }
private:
int w_, h_;
};
class Circle : public Shape {
public:
Circle(int x, int y, int r) : Shape(x, y), r_(r) {}
virtual double area() override { return r_ * r_ * 3.1415926; }
private:
int r_;
};
int main() {
Shape* shapes[] = {
new Rectangle(0, 0, 10, 20),
new Circle(0, 0, 5)
};
for (auto s : shapes) {
cout << "Area: " << s->area() << endl;
}
return 0;
}
我们通过输出两个图形的面积,来演示多态的效果。
完整的代码可以在这里找到。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈C++对象的内存分布和虚函数表 - Python技术站