background image

指针的数组,每个虚函数占用这个数组的一个 slot。一个类只有一个 VTABLE,不管它有
多少个实例。派生类有自己的 VTABLE,但是派生类的 VTABLE 与基类的 VTABLE 有相
同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。在创建类实例的时候,
编译器还会在每个实例的内存布局中增加一个 vptr 字段,该字段指向本类的 VTABLE。通
过这些手段,编译器在看到一个虚函数调用的时候,就会将这个调用改写,针对 1.1 中的
例子:

void bar(A * a)
{
    a->foo();
}

会被改写为:

void bar(A * a)
{
    (a->vptr[1])();
}

    因为派生类和基类的 foo()函数具有相同的 VTABLE 索引,而他们的 vptr 又指向不同的
VTABLE,因此通过这样的方法可以在运行时刻决定调用哪个 foo()函数。

    虽然实际情况远非这么简单,但是基本原理大致如此。

1.4 overload 和 override
    

虚函数总是在派生类中被改写,这种改写被称为 override”

。我经常混淆 overload”和

“override”这两个单词。但是随着各类 C++的书越来越多,后来的程序员也许不会再犯我
犯过的错误了。但是我打算澄清一下:

override 是指派生类重写基类的虚函数,就象我们前面 B 类中重写了 A 类中的 foo()函数。
重写的函数必须有一致的参数表和返回值(C++标准允许返回值不同的情况,这个我会

在 语法 部分简单介绍,但是很少编译器支持这个 feature)。这个单词好象一直没有什么

合适的中文词汇来对应,有人译为 覆盖 ,还贴切一些。
overload

约定成俗的被翻译为 重载 。是指编写一个与已有函数同名但是参数表不同的函

数。例如一个函数即可以接受整型数作为参数,也可以接受浮点数作为参数。
2. 虚函数的语法
    

虚函数的标志是 virtual”关键字。

2.1 使用 virtual 关键字
    考虑下面的类层次:

class A
{
public: