首页 > 解决方案 > C++从派生类中的虚函数调用非虚函数

问题描述

事实上,类似的问题也被问到这里那里,但答案并不令人满意。代码示例是

class  CBase
{
public:
    virtual void act1(){cout<<"CBase::act1()! "<<endl;  act2();}
    void act2()        {cout<<"CBase::act2()! "<<endl;  act3();}
    virtual void act3(){cout<<"CBase::act3()! "<<endl;  act4();}
    virtual void act4(){cout<<"CBase::act4()! "<<endl;  act5();}
    void act5()        {cout<<"CBase::act5()! "<<endl;    }
    virtual ~CBase(){}
} ;

class  CDerive : public  CBase
{
public:
    void act3(){cout<<"CDerive::act3()! "<<endl; act4();}
    void act4(){cout<<"CDerive::act4()! "<<endl; act5();}    
    void act5(){cout<<"CDerive::act5()! "<<endl;        }
    virtual ~CDerive(){}
} ;
int main()
{
    CBase *p=new CDerive;
    p->act1();
    cout<<endl;
    p->act5();
    delete p;
    return 0;
}

输出是

CBase::act1()! 
CBase::act2()! 
CDerive::act3()! 
CDerive::act4()! 
CDerive::act5()! 

CBase::act5()! 

关于p->act1()

相反,我认为p->act5()会打电话。CBase::act5()

原理——基类指针只能访问基类和虚函数中定义的函数,与真正的输出之间似乎存在矛盾。原因也无法从虚拟表中解释,因为CDerive::act5()甚至不在虚拟表中。所以,我的问题是

标签: c++polymorphism

解决方案


我认为这个问题的重点是对this指针的理解。编译时,真正的功能是(以CDerive::act4()为例)

void CDerive::act4(CDerive *this)
{
    cout<<"CDerive::act4()! "<<endl; 
    this->act5();
}

所以,this->act5()等价于CDerive::act5(),输出为CDerive::act5()!

但是等等,这似乎与函数相矛盾CBase::act2()。按照同样的逻辑,真正的功能应该是

void CBase::act2(CBase *this)        
{
    cout<<"CBase::act2()! "<<endl;  
    this->act3();
}

并且this->act3()会打电话CBase::act3(),这是不对的!

所以,真正的调用过程是

if func() is not a virtual function 
    this -> func() = class::func() 
else
    this -> func() = v_ptr -> v_talbe -> func()

使用上面的两个示例来演示它:

  • act5()不是虚函数,所以程序会调用CDerive::act5()
  • act3()是一个虚函数,所以程序会调用CDerive::act3()

这样逻辑一致,输出正确。


推荐阅读