类成员函数中的虚函数调用

时间:2016-04-24 11:39:03

标签: c++ polymorphism virtual-functions vtable

我理解虚函数和vtable的基本概念, 但是在下面的例子中,我不明白为什么c.A();打印出来

parent A
child

但没有Parent :: func()的虚拟关键字,它会打印出来

parent A
parent

你能让我详细了解原因吗?用v表,内存(堆,堆栈)等来解释会很棒。

感谢。

#include <iostream> 

template <class TYPE> class Parent
{
public:
    Parent() {};
    ~Parent() {};
    virtual void func() { std::cout << "parent" << std::endl; };

    void A() {
        std::cout << "parent A" << std::endl;
        func();
    }

};

template <class TYPE> class Child : public Parent <TYPE>
{
public:
    Child() {};
    ~Child() {};

    void func() { std::cout << "child" << std::endl; };
};

void main()
{
    Child<int> c;
    c.A();
}

2 个答案:

答案 0 :(得分:2)

虚拟关键字指定可以在派生类中重新定义函数,同时通过引用保留其调用属性。这基本上是多态行为的触发器。如果函数被声明为虚拟并且在派生类中重新定义,则使用vtable来选择函数的适当版本,除非指定了特定的命名空间。例如Parent :: func()。尽管具有相同的名称,但没有关键字virtual,您命名为func()的两个函数完全不同。没有可用于访问派生类的函数版本的基类的引用。它使用它所知道的唯一版本func(),它是在基类中定义的版本。

答案 1 :(得分:0)

@Pemdas给出了一个很好的解释。这是我的尝试。

c.A()告诉编译器&#34;我将调用我的父类&#34;中定义的非虚函数A.这转换为Parent::A(&c)

A中的Parent方法转换为&#34;获取对象&amp; c的vtable,抓取第一行中的函数指针,然后调用它&#34;。由于c重新实现了函数func,因此函数指针将是c函数func的实现。那就是你所看到的。