跳转至

带虚函数的类

在包含抽象函数(通常称为虚函数)的类中,程序必须知道调用哪个函数。考虑清单 4-5 中的类定义:

class foo {
public:
    foo() : myValue1(0xDEADBEEF), 
myValue2(0xBABABABA) {}
    int myValue1;
    static int myStaticValue;
foo::bar()\n"); }
    virtual void baz() { printf("call 
foo::baz()\n"); }
    virtual void barbaz() {}
    int myValue2;
};
int foo::myStaticValue = 0x12121212;
class fooa : public foo {
public:
    fooa() : foo() {}
    virtual void bar() { printf("call 
fooa::bar()\n"); }
    virtual void baz() { printf("call 
fooa::baz()\n"); }
};
class foob : public foo {
public:
    foob() : foo() {}
    virtual void bar() { printf("call 
foob::bar()\n"); }
    virtual void baz() { printf("call 
foob::baz()\n"); }
};

清单 4-5:foo、fooa 和 foob 类

类 foo 有三个虚函数:bar、baz 和 barbaz。类 fooa 和 foob 继承自类 foo,并重载了 bar 和 baz。由于 fooa 和 foob 有公共基类 foo,foo 指针可以指向它们,但程序仍然必须调用正确版本的 bar 和 baz。你可以通过执行以下代码看到这一点:

foo* _testfoo = (foo*)new fooa();
_testfoo->bar(); // 调用 fooa::bar()

输出:

call fooa::bar()

输出显示 _testfoo->bar() 调用了 fooa::bar(),尽管 _testfoo 是 foo 指针。程序知道调用哪个版本的函数,因为编译器在_testfoo 的内存中包含了一个 VF(虚函数)表。VF 表是函数地址数组,抽象类实例用它告诉程序它们的重载函数在哪里。