从基类调用虚函数

时间:2008-12-29 09:48:23

标签: 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()
{
    Base *pBase = new Derived;
    pBase->f();
    return 0;  
}

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

谢谢...

9 个答案:

答案 0 :(得分:52)

将调用派生类的g。如果要调用基础中的函数,请调用

Base::g();

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

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

在模板方法设计模式中使用以下事实:来自基础的函数可以调用虚方法并将控制转移到派生类中。对于C ++,它更好地称为Non-Virtual-Interface。它也广泛用于C ++标准库(例如,C ++流缓冲区具有函数pub...,它们调用实现真正工作的虚函数。例如pubseekoff调用受保护的seekoff)。我在这个答案中写了一个例子:How do you validate an object’s internal state?

答案 1 :(得分:6)

它是Derived :: g,除非你在Base的构造函数中调用g。因为在构造Derived对象之前调用了Base构造函数,所以Derived :: g无法在逻辑上被调用,因为它可能会操作尚未构造的变量,因此将调用Base :: g。

答案 2 :(得分:5)

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“指向”的那个。

答案:Derive :: g()

答案 3 :(得分:2)

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

Base *pBase = new Derived;
除非您拥有:

,否则

无效

Class Derived : public Base

它想要你的意思吗?如果这是你想要的意思,

pBase->f();

然后调用堆栈会像这样:

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

答案 4 :(得分:1)

由于您已将g()定义为虚拟,因此无论您的代码当前正在访问它的类型如何,都会在类的vtable中查找派生得最多的g()并调用它。

请参阅C++ FAQ on virtual functions

答案 5 :(得分:1)

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

答案 6 :(得分:0)

我认为你试图发明Template Method Pattern

答案 7 :(得分:0)

将调用派生类'方法。

这是因为在包含虚函数的类中包含了vtable,并且这些类覆盖了这些函数。 (这也称为动态调度。)以下是真正发生的事情:为Base创建了一个vtable,为Derived创建了一个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只知道g()中的Derived,所以我们使用的是Derived::g()。因此,ps aux | bla bal | xargs kill || true 被调用。

答案 8 :(得分:0)

如果在成员函数中,则将调用派生类的

g()。

如果在构造函数或析构函数中,将调用基类的

g()。

https://www.geeksforgeeks.org/calling-virtual-methods-in-constructordestructor-in-cpp/

// 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