关于虚拟函数的静态调用


当用类域操作符调用虚拟函数时,我们改变了虚拟机制,使得虚拟函数在编译时刻被静态解析。例如,假设我们已经为一个基类Based及从它派生的一个类Derived都定义了虚拟函数func():

   
  Based *ptr1 = new Derived();
  
//通过虚拟机制动态调用函数func()
//调用Derived::func()实例
ptr1->func();
//在编译时刻静态调用func();
//调用Based::func()实例
ptr1->Based::func();

Based::func()的显示调用在编译时刻被解析为基类Based的实例,机试指针ptr1指向一个Derived对象、

那么,我们为什么要改变虚拟机制呢?这样做的好处是什么?我们应该在什么场合使用它?

面向对象 C++

1998fox 12 years, 6 months ago

这样的使用场景通常是这样的,假设基类,即Based类处理的是键盘消息的类,Derived派生自Based。用如下代码表示

   
  class Based//基类,用来处理键盘消息
  
{
public:
//func函数,捕获键盘消息进行处理,例如只处理了A B C三个键
virtual void func();
};

class Derived : public Based
{
public:
//额外的消息的处理,例如除了A B C之外,还要处理D E F
virtual void func();
}

这个时候,使用ptr1->func();的时候,完成的是派生类的部分,也就是处理了DEF,但是并不想破坏原来流程,所以使用ptr1->Based::func();来调用基类的func函数。
这个例子举的不是很好,因为一般情况下,都会在Derived类中用Based::func()这个语句去调用基类的func函数。
但是说一个题外的但是很容易发生错误的问题就是,使用ptr1->Based::func()这种方法去调用基类的函数是没问题的,但是切记不能这么去调用static_cast<Based *>(ptr1)->func();这样虽然也是调用到了基类的func函数。但是存在一个很严重的问题是这个函数会调用一个ptr1的base部分的副本去调用func函数,然后假设func中有改变基类部分的行为的话,就会导致改变的其实是base部分的副本(虽然读起来有点拗口,但是很重要),改变的并不是当前的这个派生类对象。这就会导致这个派生类对象编程一个残缺的对象。所以一定要注意。

落魄的丶华丽 answered 12 years, 6 months ago

Your Answer