相同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。在创建类实例的时候,
编译器还会在每个实例的内存布局中增加一个 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
“
”
约定成俗的被翻译为 重载 。是指编写一个与已有函数同名但是参数表不同的函
数。例如一个函数即可以接受整型数作为参数,也可以接受浮点数作为参数。
二.
虚函数的语法
“
虚函数的标志是 virtual”关键字。
2.1 使用 virtual
关键字
考虑下面的类层次:
class A
{
public:
virtual void foo();
};