C++ 来自基类的虚拟函数调用
假设我们有:C++ 来自基类的虚拟函数调用,c++,polymorphism,virtual,C++,Polymorphism,Virtual,假设我们有: 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() { B
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;
}
将从Base::f()
调用哪个g()
<代码>基::g()或派生::g()
谢谢 将调用派生类的g。如果要调用基函数中的函数,请调用
Base::g();
相反。如果要调用派生版本,但仍要调用基本版本,请安排g的派生版本在其第一条语句中调用基本版本:
virtual void g() {
Base::g();
// some work related to derived
}
模板方法设计模式中使用了这样一个事实:基函数可以调用虚方法,控制权被转移到派生类中。对于C++,它更为著名。它在C++标准库中也有广泛的应用(C++流缓冲区,例如函数,代码,代码,…,代码),调用真正的工作的虚拟函数。例如,代码> PUBEXKOOFF < /代码>调用受保护的<代码> SekOff<<代码>。我在这个答案中写了一个这样的例子:我认为您试图发明因为您已经将g()定义为虚拟的,最派生的g()将在类的vtable中查找并调用,而不管您的代码当前访问它的类型是什么
请参阅。好的。。。我不确定这是否应该编译。以下:
Base *pBase = new Derived;
无效,除非您有:
Class Derived : public Base
你的意思是想要吗?如果这是你的意思
pBase->f();
然后调用堆栈将如下所示:
Derived::f()
Base::f()
Derived::g()
实际运行代码表明调用了派生的::g()。 pBase=new-Derived返回指向派生is-a基的指针 因此pBase=new-Derived是有效的 pBase引用了一个基,所以它看起来就像是一个基一样 pBase->f()将调用派生::f() 然后我们在代码中看到: 派生::f()-->Base::f()-->g()-但哪个g 它调用了派生::g(),因为pBase“指向”的是g
答:派生::g()它是派生::g,除非在Base的构造函数中调用g。因为基本构造函数是在构造派生对象之前调用的,所以不能从逻辑上调用派生的::g,因为它可能会操作尚未构造的变量,所以将调用Base::g。将调用派生类的方法 这是因为在具有虚拟函数的类和重写这些函数的类中包含vtable。(这也称为动态调度。)实际情况如下:为
Base
创建vtable,为派生的
创建vtable,因为每个类只有一个vtable。由于pBase
调用的函数是虚函数和超码函数,因此会调用指向派生的
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()
,所以我们使用的就是这个。因此,将调用派生的::g()。g()派生类将在成员函数中调用
如果在构造函数或析构函数中,将调用基类的g()
请使用上面有1/0'ers的按钮来很好地格式化代码。(我编辑了它,但是OP回滚了它。所以我自己不会再编辑它了)请注意,你给出了一个内存泄漏的例子。您在main中有一个被遗忘的delete。很好地解释了构造函数中发生的事情。
Scott Meyers说,有趣的是,我发现GCC 4.8.2有一个问题:
Base*pBase=(Base*)(void*)new-Derived代码>尝试从基类调用纯虚函数。如果在构造函数中调用,将调用g()基类,因为派生类现在未构造。
// calling virtual methods in constructor/destructor
#include<iostream>
using namespace std;
class dog
{
public:
dog()
{
cout<< "Constructor called" <<endl;
bark() ;
}
~dog()
{
bark();
}
virtual void bark()
{
cout<< "Virtual method called" <<endl;
}
void seeCat()
{
bark();
}
};
class Yellowdog : public dog
{
public:
Yellowdog()
{
cout<< "Derived class Constructor called" <<endl;
}
void bark()
{
cout<< "Derived class Virtual method called" <<endl;
}
};
int main()
{
Yellowdog d;
d.seeCat();
}
Constructor called
Virtual method called
Derived class Constructor called
Derived class Virtual method called
Virtual method called