提问者:小点点

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()

  • 由于act1()是虚函数,派生类不实现它,因此程序将调用CBASE::act1()
  • 则程序将调用CBASE::act2()
  • act3()是一个常规函数,程序将调用cdervie::act3()
  • act4()也是一个常规函数,程序将调用cdervie::act4()
  • 我不明白的部分来了,act5()不是虚函数,p是属于cbase的指针,基本上p只能访问cbase中的函数!但输出是cderive::act5()!

相比之下,p->act5()会像我想的那样调用CBASE::act5()

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

  • 这背后的理由是什么?
  • cbase*p=new cderivecderive A;CBase*P=&A

共1个答案

匿名用户

我将重新陈述你的要点,并对它们做一些小的修改。

  • act1()是一个非抽象的、公共的虚函数,它存在于cbase中,而不存在于cderive中,因此p使用了cbase中的实现。因为它是在CBASE中实现的,所以不需要在子类中重写
  • 与上面act2()相同。请注意,act2()是非虚拟
  • act3()是CBASE中的虚函数,在CDerive中被重写。由于P被分配为CDerive,因此使用重写,并从CDerive`
  • 调用ACT3()
  • 与上述act4()
  • 相同
  • 因为上面的act4()是从CDerive对象调用的,所以对act5()的调用也将来自CDerive

新建项目符号:

  • 然后在main中,这行p->act5()调用CBASE版本。这是因为PCBASE*act5()不是虚拟的。因此它从cbase
  • 调用

相关问题


MySQL Query : SELECT * FROM v9_ask_question WHERE 1=1 AND question regexp '(c++|派生类|中|虚|函数|调用|非虚|函数)' ORDER BY qid DESC LIMIT 20
MySQL Error : Got error 'repetition-operator operand invalid' from regexp
MySQL Errno : 1139
Message : Got error 'repetition-operator operand invalid' from regexp
Need Help?