来自基类的虚函数调用
假设我们有:
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()
被调用。