我理解虚函数和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();
}
答案 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
的实现。那就是你所看到的。