当前位置: 首页 > 知识库问答 >
问题:

C++从派生类中虚函数调用非虚函数

卓星波
2023-03-14

其实,类似的问题这里问过,那里问过,但回答都不满意。代码示例是

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个答案

曾宏毅
2023-03-14

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

  • 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
  • 调用

 类似资料:
  • 我正在学习面向对象的C,并有一个关于虚拟/纯虚拟和多级继承的问题。 假设我有这样的简单代码: 我的理解是,除非getWidth被指定为虚拟,否则多态将使用“Base”类的函数。我的意思是r-的最终调用 在这种情况下,我注意到如果我删除Shape中的纯虚拟声明,我们会得到我刚才描述的行为。在基类中有一个纯虚函数会自动使该函数的所有定义都是虚的吗?

  • 为什么一个虚函数在派生类中默认是虚的,甚至不可能在派生类中完全移除虚性,这有什么好的理由吗? 我希望这种行为的原因与我不希望默认情况下每个函数都是的原因相同。编译器可能会生成牺牲性能的vtables。 基类应该有一个vtable(我想要多态性在那里),但派生类没有vtable(我不希望多态性在那里,为什么我要那样,只是因为它派生了一个具有多态性的类?)。 我想解决的问题是更好地理解虚函数。我只是没

  • 我在嵌入式环境中使用 C,其中虚拟函数的运行时确实很重要。我读过关于可以内联虚拟函数的罕见情况,例如:内联虚函数真的是无意义的吗?接受的答案指出,只有在运行时已知确切的类时,例如在处理本地、全局或静态对象(不是指针或对基类型的引用)时,才有可能进行内联。我理解这背后的逻辑,但我想知道在以下情况下是否也可以内联: 从我的观点来看,编译器应该在编译时知道的最终类型,因为它是一个最终类。在这种情况下,是

  • 本文向大家介绍C++中虚函数与纯虚函数的用法,包括了C++中虚函数与纯虚函数的用法的使用技巧和注意事项,需要的朋友参考一下 本文较为深入的分析了C++中虚函数与纯虚函数的用法,对于学习和掌握面向对象程序设计来说是至关重要的。具体内容如下: 首先,面向对象程序设计(object-oriented programming)的核心思想是数据抽象、继承、动态绑定。通过数据抽象,可以使类的接口与实现分离,使

  • 问题内容: 如何使用C ++从派生类调用父函数?例如,我有一个名为的类,一个名为的类是从父类派生的。每个类中都有一个print函数。在定义孩子的打印功能时,我想调用父母的打印功能。我将如何去做呢? 问题答案: 我冒着明显的危险:调用该函数,如果它在基类中定义,则该函数在派生类中自动可用(除非它是private)。 如果派生类中有一个具有相同签名的函数,则可以通过在基类名称后加上两个冒号来消除歧义。

  • 本文向大家介绍c++中虚函数和纯虚函数的作用与区别,包括了c++中虚函数和纯虚函数的作用与区别的使用技巧和注意事项,需要的朋友参考一下 虚函数为了重载和多态的需要,在基类中是有定义的,即便定义是空,所以子类中可以重写也可以不写基类中的此函数! 纯虚函数在基类中是没有定义的,必须在子类中加以实现,很像java中的接口函数! 虚函数 引入原因:为了方便使用多态特性,我们常常需要在基类中定义虚函数。 纯