我正在根据自己的理解做一些练习。在编译下面的代码时,我得到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();
}
输出:
派生::详细显示()
衍生::打印()
答案 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()。