假设我们有:
class Base
{
virtual void f() {g();};
virtual void g(){//Do some Base related code;}
};
class Derived : public Base
{
virtual void f(){Base::f();} override;
virtual void g(){/*Do some Derived related code*/} override;
};
int main()
{
Base *pBase = new Derived;
pBase->f();
return 0;
}
将从Base::f()
调用哪个g()
?Base::g()
还是Derived::g()
?
谢谢你...
9条答案
按热度按时间slsn1g291#
将调用派生类的g。如果要调用基类中的函数,请调用
如果你想调用派生版本,但仍然想让基版本被调用,那么安排g的派生版本在它的第一条语句中调用基版本:
来自基类的函数可以调用虚方法并且控制权被转移到派生类的事实被用在模板方法设计模式中。它通常被称为Non-Virtual-Interface,它也广泛用于C标准库中(例如,C流缓冲区具有函数
pub...
,该函数调用执行真实的工作的虚函数。例如,pubseekoff
调用受保护的seekoff
)。我在下面的回答中举了一个例子:如何验证对象的内部状态?pgpifvop2#
它是Derived::g,除非你在Base的构造函数中调用g。因为Base构造函数在Derived对象构造之前被调用,Derived::g在逻辑上不能被调用,因为它可能操作尚未构造的变量,所以Base::g将被调用。
lrpiutwd3#
pBase是指向基址的指针。pBase = new Derived返回指向Derived的指针- Derived是基址。
因此pBase =新衍生是有效的。
pBase引用了一个Base,因此它会将Derived视为Base。
pBase-〉f()将调用Derive::f();
然后我们在代码中看到:
推导::f()--〉基::f()--〉g()--但哪个g??
它调用Derive::g(),因为这是pBase“指向”的g。
答案:推导::g()
puruo6ea4#
嗯......我不确定这个是否可以编译。下面,
无效,除非您具有:
你指的是想要吗?如果你指的是想要,
然后调用堆栈将如下所示:
zpgglvta5#
由于您已经将g()定义为虚拟的,因此无论代码当前访问的是什么类型,都将在类的vtable中查找并调用派生程度最高的g()。
请参见C++ FAQ on virtual functions。
of1yzvn46#
实际运行代码显示Derived::g()被调用。
5lwkijsr7#
如果在成员函数中,将调用派生类的g()。
如果在构造函数或析构函数中,则调用基类的g()。
https://www.geeksforgeeks.org/calling-virtual-methods-in-constructordestructor-in-cpp/
输出:
6qfn3psc8#
我觉得你想发明Template Method Pattern
snvhrwxg9#
将调用派生类的方法。
这是因为在具有虚函数的类和覆盖这些函数的类中包含了vtable。(这也称为动态分派。) 下面是实际情况:为
Base
创建一个vtable,为Derived
创建一个vtable,因为每个类只有一个vtable。由于pBase
调用的函数是虚拟的且被覆盖,因此将调用指向Derived
的vtable的指针。将其称为d_ptr
,也称为vpointer:现在,d_ptr调用
Derived::f()
,Derived::f()
调用Base::f()
,Base::f()
查看vtable以确定使用哪个g()
,因为vpointer只知道Derived
中的g()
,所以我们使用Derived
,因此,Derived::g()
被调用。