虚函数布局

来源:百度文库 编辑:神马文学网 时间:2024/05/21 04:32:57
c++虚函数表详解收藏

编译器将虚函数表在编译时存放在对象的头部,因此我们可以自由的访问虚函数。
1. 访问对象的数函数表。
比如有这样一个类:
class A
{
public:
 virtual int test1()
 {
  printf("A::test1\n");
  return 0;
 }

 virtual int test2()
 {
  printf("A::test2\n");
  return 0;
 }

 virtual int test3()
 {
  printf("A::test3\n");
  return 0;
 }
};

// 创建A的对象a
A a;

通过查找虚函数表来访问该对象的虚函数:
typedef int (* FUNC)(void);

FUNC func = (FUNC)*(int *)*((int *)&a + 0);
func();

func = (FUNC)*((int *)*(int *)&a + 1);
func();

func = (FUNC)*((int *)*(int *)&a + 2);
func();

对象a的虚函数表布局
A::test1 A::test2 A::test3

2. 子类重载了父类的虚函数。
比如:
class B:public A
{
public:
 virtual int test1()
 {
  printf("B::test1\n");
  return 0;
 }
};

那么对象b的虚函数表布局应该是:
B::test1 A::test2 A::test3

3. 子类没有重载父类的虚函数
比如:
class B:public A
{
public:
 virtual int test4()
 {
  printf("B::test4\n");
  return 0;
 }
};
那么对象b的虚函数表布局应该是:
A::test1 A::test2 A::test3 B::test1

4. 多重继承,有重载。
比如:
class A
{
public:
 virtual int test1()
 {
  printf("A::test1\n");
  return 0;
 }

 virtual int test2()
 {
  printf("A::test2\n");
  return 0;
 }

 virtual int test3()
 {
  printf("A::test3\n");
  return 0;
 }
};

class C
{
public:
 virtual int test1()
 {
  printf("C::test1\n");
  return 0;
 }

 virtual int test4()
 {
  printf("C::test4\n");
  return 0;
 }
};

class B:public A, public C
{
public:
 virtual int test1()
 {
  printf("B::test1\n");
  return 0;
 }
};

那么对象b的虚函数表布局应该是:
B::test1 A::test2 A::test3
B::test1 C::test4

5. 多重继承,没有重载。
class B:public A, public C
{
public:
 virtual int test5()
 {
  printf("B::test5\n");
  return 0;
 }
};

那么对象b的虚函数表布局应该是:
A::test1 A::test2 A::test3 b::test5
C::test1 C::test4