C++多态的实现(虚函数的应用)

2021年09月15日 阅读数:3
这篇文章主要向大家介绍C++多态的实现(虚函数的应用),主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

c++实现多态的方法

其实不少人都知道,虚函数在c++中的实现机制就是用虚表和虚指针,可是具体是怎样的呢?从more effecive c++其中一篇文章里面能够知道:是每一个类用了一个虚表,每一个类的对象用了一个虚指针。具体的用法以下:

class A
{
public:
   virtual void f();
   virtual void g();
private:
   int a
};

class B : public A
{
public:
   void g();
private:
   int b;
};

//A,B的实现省略

由于A有virtual void f(),和g(),因此编译器为A类准备了一个虚表vtableA,内容以下:

c++

A::f 的地址
A::g 的地址

B由于继承了A,因此编译器也为B准备了一个虚表vtableB,内容以下:

A::f 的地址
B::g 的地址

注意:由于B::g是重写了的,因此B的虚表的g放的是B::g的入口地址,可是f是从上面的A继承下来的,因此f的地址是A::f的入口地址。

而后某处有语句 B bB;的时候,编译器分配空间时,除了A的int a,B的成员int b;之外,还分配了一个虚指针vptr,指向B的虚表vtableB,bB的布局以下:

vptr : 指向B的虚表vtableB
int a: 继承A的成员
int b: B成员

当以下语句的时候:
A *pa = &bB;

pa的结构就是A的布局(就是说用pa只能访问的到bB对象的前两项,访问不到第三项int b)

那么pa->g()中,编译器知道的是,g是一个声明为virtual的成员函数,并且其入口地址放在表格(不管是vtalbeA表仍是vtalbeB表)的第2项,那么编译器编译这条语句的时候就如是转换:call *(pa->vptr)[1](C语言的数组索引从0开始哈~)。

这一项放的是B::g()的入口地址,则就实现了多态。(注意bB的vptr指向的是B的虚表vtableB)

另外要注意的是,如上的实现并非惟一的,C++标准只要求用这种机制实现多态,至于虚指针vptr到底放在一个对象布局的哪里,标准没有要求,每一个编译器本身决定。我以上的结果是根据g++ 4.3.4通过反汇编分析出来的。