来自基类的虚函数调用

假设我们有:

Class Base { virtual void f(){g();}; virtual void g(){//Do some Base related code;} }; Class Derived : public Base { virtual void f(){Base::f();}; virtual void g(){//Do some Derived related code}; }; int main() { Base *pBase = new Derived; pBase->f(); return 0; } 

哪个g()将从Base::f()调用? Base::g()Derived::g()

谢谢…

派生类的g将被调用。 如果你想调用基地的function,请致电

 Base::g(); 

代替。 如果你想调用派生的,但仍然希望调用基本版本,安排派生版本的g在其第一个语句中调用基本版本:

 virtual void g() { Base::g(); // some work related to derived } 

在模板方法devise模式中使用来自基础的function可以调用虚拟方法并将控制转移到派生类中的事实。 对于C ++来说,它被称为非虚拟接口 。 它也广泛用于C ++标准库(例如,C ++stream缓冲区具有函数pub... ,调用实际工作的虚拟函数,例如pubseekoff调用受保护的seekoff )。 我在这个答案中写了一个例子: 你如何validation一个对象的内部状态?

pBase是一个指向基地的指针。 pBase = new Derived返回指向Derived – Derived is-a Base的指针。

所以pBase = new Derived是有效的。

pBase引用一个Base,所以它将看作Derived,就像它是一个Base。

pBase-> f()将调用Derive :: f();

然后我们在代码中看到:

Derive :: f() – > Base :: f() – > g() – 但哪个g?

那么,它会调用Derive :: g(),因为那是pBase“指向”的g。

答案:派生:: g()

它是Derived :: g,除非在Base的构造函数中调用g。 由于在创buildDerived对象之前调用Base构造函数,所以Derived :: g无法在逻辑上调用,因为它可能会操作尚未构造的variables,所以将调用Base :: g。

那么…我不确定这应该编译。 下列,

 Base *pBase = new Derived; 

除非你有:

 Class Derived : public Base 

这是你的意思吗? 如果这是你的意思,

 pBase->f(); 

然后调用堆栈会像这样:

 Derived::f() Base::f() Derived::g() 

正如你所定义的g()是虚拟的,大多数派生的g()将在类的vtable中被调用并被调用,而不pipe你的代码当前正在访问它的types。

有关虚函数的信息,请参阅C ++ FAQ 。

实际上运行你的代码显示Derived :: g()被调用。

我想你试图发明模板方法模式

派生类的方法将被调用。

这是因为在具有虚拟函数的类中包含了vtables,并且这些类覆盖了这些函数。 (这也被称为dynamic分派。)以下是真正发生的事情:为Base创build一个vtable,并为Derived创build一个vtable,因为每个类只有一个vtable。 因为pBase正在调用一个虚拟的函数,所以调用一个指向Derived的vtable的指针。 称之为d_ptr ,也称为vpointer:

 int main() { Base *pBase = new Derived; pBase->d_ptr->f(); return 0; } 

现在,d_ptr调用Derived::f() ,它调用Base::f() ,然后查看vtable以查看要使用的g() 。 因为vpointer只知道Derived中的g() ,所以就是我们使用的那个。 因此, Derived::g()被调用。