C++虚表详解

时间:2024-01-03 21:22:32

所有结果均为32位系统,指针为4个字节

简单继承

class A {
public:
int a;
}; class B : public A {
public:
int b;
};

对象B的内存布局:

b --> +-----------+
| a |
+-----------+
| b |
+-----------+

简单继承虚函数

class A {
public:
int a;
virtual void v();
}; class B : public A {
public:
int b;
};

对象B内存布局

/*
+-----------------------+
| 0 (top_offset) |
+-----------------------+
b --> +----------+ | ptr to typeinfo for B |
| vtable |-------> +-----------------------+
+----------+ | A::v() |
| a | +-----------------------+
+----------+
| b |
+----------+

简单多重继承

class A {
public:
int a;
virtual void v();
}; class B {
public:
int b;
virtual void w();
}; class C : public A, public B {
public:
int c;
};

对象C的内存布局

/*

                           +-----------------------+
| 0 (top_offset) |
+-----------------------+
c --> +----------+ | ptr to typeinfo for C |
| vtable |-------> +-----------------------+
+----------+ | A::v() |
| a | +-----------------------+
+----------+ | -8 (top_offset) |
| vtable |---+ +-----------------------+
+----------+ | | ptr to typeinfo for C |
| b | +---> +-----------------------+
+----------+ | B::w() |
| c | +-----------------------+
+----------+

简单多重继承(虚函数)


class A {
public:
int a;
virtual void v();
}; class B {
public:
int b;
virtual void w();
}; class C : public A, public B {
public:
int c;
void w();
};

对象C的内存布局:

/*

                           +-----------------------+
| 0 (top_offset) |
+-----------------------+
c --> +----------+ | ptr to typeinfo for C |
| vtable |-------> +-----------------------+
+----------+ | A::v() |
| a | +-----------------------+
+----------+ | C::w() |
| vtable |---+ +-----------------------+
+----------+ | | -8 (top_offset) |
| b | | +-----------------------+
+----------+ | | ptr to typeinfo for C |
| c | +---> +-----------------------+
+----------+ | thunk to C::w() |
+-----------------------+

菱形继承

class A {
public:
int a;
virtual void v();
}; class B : public A {
public:
int b;
virtual void w();
}; class C : public A {
public:
int c;
virtual void x();
}; class D : public B, public C {
public:
int d;
virtual void y();
};

对象D的内存布局:

/*

                           +-----------------------+
| 0 (top_offset) |
+-----------------------+
d --> +----------+ | ptr to typeinfo for D |
| vtable |-------> +-----------------------+
+----------+ | A::v() |
| a | +-----------------------+
+----------+ | B::w() |
| b | +-----------------------+
+----------+ | D::y() |
| vtable |---+ +-----------------------+
+----------+ | | -12 (top_offset) |
| a | | +-----------------------+
+----------+ | | ptr to typeinfo for D |
| c | +---> +-----------------------+
+----------+ | A::v() |
| d | +-----------------------+
+----------+ | C::x() |
+-----------------------+

菱形继承(虚继承)

class A {
public:
int a;
virtual void v();
}; class B : public virtual A {
public:
int b;
virtual void w();
}; class C : public virtual A {
public:
int c;
virtual void x();
}; class D : public B, public C {
public:
int d;
virtual void y();
};

对象D的内存布局:

/*

                                   +-----------------------+
| 20 (vbase_offset) |
+-----------------------+
| 0 (top_offset) |
+-----------------------+
| ptr to typeinfo for D |
+----------> +-----------------------+
d --> +----------+ | | B::w() |
| vtable |----+ +-----------------------+
+----------+ | D::y() |
| b | +-----------------------+
+----------+ | 12 (vbase_offset) |
| vtable |---------+ +-----------------------+
+----------+ | | -8 (top_offset) |
| c | | +-----------------------+
+----------+ | | ptr to typeinfo for D |
| d | +-----> +-----------------------+
+----------+ | C::x() |
| vtable |----+ +-----------------------+
+----------+ | | 0 (vbase_offset) |
| a | | +-----------------------+
+----------+ | | -20 (top_offset) |
| +-----------------------+
| | ptr to typeinfo for D |
+----------> +-----------------------+
| A::v() |
+-----------------------+
  • 这里需要注意,因为A中有虚函数,所以虚基类A前面必须带有虚表指针。

如果A中没有虚函数

class A {
public:
int a;
void v();
}; class B : public virtual A {
public:
int b;
virtual void w();
}; class C : public virtual A {
public:
int c;
virtual void x();
}; class D : public B, public C {
public:
int d;
virtual void y();
};

对象D的内存布局:

/*

                                   +-----------------------+
| 20 (vbase_offset) |
+-----------------------+
| 0 (top_offset) |
+-----------------------+
| ptr to typeinfo for D |
+----------> +-----------------------+
d --> +----------+ | | B::w() |
| vtable |----+ +-----------------------+
+----------+ | D::y() |
| b | +-----------------------+
+----------+ | 12 (vbase_offset) |
| vtable |---------+ +-----------------------+
+----------+ | | -8 (top_offset) |
| c | | +-----------------------+
+----------+ | | ptr to typeinfo for D |
| d | +-----> +-----------------------+
+----------+ | C::x() |
| a | +-----------------------+
+----------+