例子如下:
class B {
public:
void mf();
};
class D : public B {};
D x; // x是一个类型为D的对象
// 方式一
B* pB = &x // 获得一个pB 指向 x
pB->mf(); // 经由指针调用mf
// 方式二
D* pD = &x // 获得一个指针指向x
pD->mf(); // 经由指针调用mf
我们期望方式一和方式二调用mf 的表现是一致的。但是如果 D的实现如下
class D : public B {
public:
void mf(); // 遮掩了B
};
此时方式一和方式二的表现形式就不一致了,造成这一行为的原因是: non-virtual 函数是 B::mf和D::mf都是静态绑定。意思是,由于pB是申明为指向B的指针,通过pB调用non-virtual函数永远是B所定义的版本,即时pB指向一个类型为B的派生类。
但是 virtual 函数却是动态绑定的。所以最后调用mf的时候都是调用了实际的类的哪个mf。
测试一下:
class B {
public:
void mf()
{
std::cout << "B::mf()" << std::endl;
}
};
class D : public B {
public:
void mf()
{
std::cout << "D::mf()" << std::endl;
}
};
int main()
{
D d;
std::cout << "call d.mf(): ";
d.mf(); // D::mf()
B* pb = &d;
std::cout << "call pb->mf(): ";
pb->mf(); // B::mf()
D* pd = &d;
std::cout << "call pd->mf(): ";
pd->mf(); // D::mf()
return 0;
}
输出:
call d.mf(): D::mf()
call pb->mf(): B::mf()
call pd->mf(): D::mf()