C ++虚函数行为

时间:2015-12-06 08:43:58

标签: c++ virtual-functions

我正在根据自己的理解做一些练习。在编译下面的代码时,我得到Derived :: disp()调用,然后调用非虚函数" Print"。

我的问题是为什么要调用Derived class" Print"版本而不是基本打印版本甚至" Print"不是虚拟的。

class Base
{
public:
     void print(){
        cout<<"Base::Print()\n";
    }
 virtual void disp(){
    cout<<"Base::Disp()\n";
    }
};

class Derived: public Base
{
public:
    void print(){
        cout<<"Derived::Print()\n";
    }
    void disp(){
    cout<<"Derived::Disp()\n";
    print();
    }
};

void main()
{
    Base *pB = new Derived();

    pB->disp();
}

输出:
派生::详细显示()
衍生::打印()

3 个答案:

答案 0 :(得分:5)

如果在(虚拟或非虚拟)成员函数内调用了非虚函数,则调用该类的成员函数。

如果您在主电话中拨打pB->print(),则会拨打Base::Print。但就目前情况而言,pB->Disp()调用Derived::Disp()会调用Derived::Print,因为它是从Derived类内部调用的。

答案 1 :(得分:1)

在非静态成员函数的主体内,关键字this具有指向调用该函数的类类型的对象的指针类型。

如果为派生类调用虚函数,则this具有此类指针的类型。

内部成员函数对类成员的访问可以在程序的上下文中查找,例如

( *this ).print();

其中this的类型为Derived *

因此调用此类的成员函数print

答案 2 :(得分:0)

对于编译器,virtual意味着对于对该函数的调用,应首先查询v-table,以找到该函数的真实位置,而不是使用该实例的静态类型。这样,您对disp()的调用就会到达Derived中的代码。在派生中,您可以使用以下命令调用基类的打印功能:

Base::print();

但默认情况下,print()将调用Derived :: print()。 v-table跳转已经完成,因此在该函数中,静态类型为&#34; this&#34;众所周知。它有助于考虑C ++中的类布局:

Derived {
  Base {
    print();
    virtual disp();
  }
  print();
  disp();
}

虚拟是第一次调用所必需的,因为编译器看到一个Base,所以从main开始,如果你调用pB-&gt; print(),它将查看对应于print函数的偏移量,而对于disp,它将找到一个v表条目并将其跳转到Derived :: disp()。