【问题标题】:why virtual function give segmentation fault为什么虚函数会给出分段错误
【发布时间】:2016-07-13 02:55:40
【问题描述】:
#include <iostream> 
using namespace std; 

/*
 *   base class
 */ 
class A
{
 public: 
    A()
    {
        this->init(); 
    }

    virtual void init()
    {
        cout << " A"; 
    }
    // in public, so class B can call it. 
    void testit()
    {
        this->init(); 
    }
}; 

/*
 * child class
*/ 
class B : public A
{
public:
    B()
    {
       this->init(); 
    }

    virtual void init()
    {
        // here get segmentation fault. 
        // but if call A::init() then it is ok. 
        A::testit();
        // if call A::init(); then it working. 
        cout << "B" ; 
    }

}; 

int main()
{   

      B b; 
      A * a = &b; 
      // here B virtual function will be called. 
      a->init(); 
      return 0; 

}

基本上这是一个虚拟功能测试。但是我发现当子类在自己的虚函数中调用基类函数时,会出现运行时分段错误。为什么?

在这里,当运行时它在 A::testit() 处出现分段错误 但为什么?

为什么子实例调用基函数会出错?

【问题讨论】:

    标签: c++ segmentation-fault runtime-error virtual-functions


    【解决方案1】:
    // but if call A::init() then it is ok. 
    A::testit();
    

    您在A::testit() 中呼叫init()init()是虚的,那么B::init()会在当前实际对象为B时被递归调用,最后变成无限递归。

    如果你显式调用A::init() 会避免无限递归,那就没问题了。

    【讨论】:

      【解决方案2】:

      简而言之,分段错误是由于无限递归造成的。 B::init 调用A::testit,后者调用对象的init。由于对象属于B类,这意味着A::testit会调用B::init,后者又会调用A::testit,以此类推。

      为什么这样做而不是显式调用A::init?嗯,这是一个多态的例子。在这种情况下,B::init 内部的this 指针指向类B 的对象。由于B 覆盖了A 的虚拟init 方法,因此对该对象的init 的任何调用都将调用B 中的覆盖方法。所以B::init() 正在调用A::testit(),它在一个无限循环中调用B::init()。要调用父版本的init,您必须显式调用它(A::init)。

      【讨论】:

      • 需要注意的是,在A的构造函数或析构函数内部调用对象的init方法时,不会调用B::init。这是因为this 指针在这些阶段没有指向B 类的对象,而是指向A 类的对象,所以任何对init 的调用都会调用A::init。多态不会在构造函数和析构函数中将虚方法调用分派给派生类,因为派生类在这些阶段不存在。
      猜你喜欢
      • 2021-04-27
      • 2011-09-13
      • 2020-08-22
      • 1970-01-01
      • 1970-01-01
      • 2021-07-19
      • 1970-01-01
      • 2014-03-31
      相关资源
      最近更新 更多