关于c ++:来自基类的虚函数调用

virtual function call from base class

说我们有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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。如果要调用基函数,请调用

1
Base::g();

相反。如果要调用派生版本,但仍要调用基版本,请安排G的派生版本在其第一条语句中调用基版本:

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

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


它是派生的::g,除非在基的构造函数中调用g。因为在构造派生对象之前调用了基构造函数,所以不能在逻辑上调用派生::g,因为它可能操作尚未构造的变量,所以将调用基::g。


pbase是指向基的指针。pbase=new derived返回指向派生is-a基的指针。

所以pbase=new derived是有效的。

pbase引用了一个基,所以它将把派生看作是一个基。

pbase->f()将调用派生::f();

然后我们在代码中看到:

派生::f()-->base::f()-->g()-但哪个g??

好吧,它调用了派生::g(),因为这是pbase"指向"的g。

答案:派生::g()


好。。。我不确定这应该编译。以下,

1
Base *pBase = new Derived;

无效,除非:

1
Class Derived : public Base

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

1
pBase->f();

然后调用堆栈如下所示:

1
2
3
Derived::f()
    Base::f()
        Derived::g()

实际上,运行代码表明调用了派生的::g()。


正如您将g()定义为虚拟的那样,最派生的g()将在类的vtable中查找并调用,而不管您的代码当前访问的类型是什么。

有关虚拟函数的C++ FAQ。


将调用派生类的方法。

这是因为在具有虚拟函数的类和重写这些函数的类中包含vtables。(这也被称为动态调度。)下面是实际情况:vtable是为Base创建的,vtable是为Derived创建的,因为每个类只有一个vtable。由于pBase正在调用虚函数和overrode函数,因此调用指向Derived的vtable的指针。称之为d_ptr,也称为vpointer:

1
2
3
4
5
6
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()


我想你是想发明模板方法模式