C++ 基类对象调用派生类函数(非虚拟)时会发生什么情况
如果你觉得这个问题很傻,请原谅。我是一个C++新手,我在研究朗姆酒时间多态性。我想知道基类对象调用派生类函数(非虚拟)时会发生什么。例如,看看代码C++ 基类对象调用派生类函数(非虚拟)时会发生什么情况,c++,polymorphism,C++,Polymorphism,如果你觉得这个问题很傻,请原谅。我是一个C++新手,我在研究朗姆酒时间多态性。我想知道基类对象调用派生类函数(非虚拟)时会发生什么。例如,看看代码 class base { public: virtual void vfunc() {cout << "This is base's vfunc().\n";} }; class derived1 : public base { public: void vfunc() {cout <
class base {
public:
virtual void vfunc() {cout << "This is base's vfunc().\n";}
};
class derived1 : public base {
public:
void vfunc() {cout << "This is derived1's vfunc().\n";}
};
int main()
{
base *p, b;
derived1 d1;
p = &b;
p->vfunc();
p = &d1;
p->vfunc();
return 0;
}
如果有人能解释这两种情况下发生了什么(指针操作方面),我将非常感激
谢谢这里的情况是有两个vtable,一个用于base,一个用于派生。在base的vtable中,有一个条目用于
vfunc()
,而在派生的vtable中,也有一个条目,诀窍是,当派生获取其父级的vtable时,它会查看它是否覆盖了其父级的任何虚拟方法,并且是。所以它取代了原来的版本,现在它指向了它自己的版本
换句话说,当您通过base类型的实例调用vfunc()
时,您将检查包含指向base的vfunc()
指针的base vtable。通过派生实例调用它时,会找到指向派生的vfunc()
的指针
如果删除virtual关键字,编译器将不再寻找虚拟函数,因此它不是基于对象的运行时类型,而是基于对象的静态/编译时类型
换句话说,如果没有virtual关键字,编译器会查看指针的类型,即base,因此每次都会调用base版本。在虚拟情况下,在运行时,
p->vfunc()
告诉p
转到类的类定义(内存中的任何部分)指针对象所属,并读取其vtable(或类似的替代实现)以确定要调用哪个函数
假设vtables如下所示:
base
的vtable:
----------------
vfunc | 0x2048
----------------
----------------
vfunc | 0x2096
----------------
derived1
的vtable:
----------------
vfunc | 0x2048
----------------
----------------
vfunc | 0x2096
----------------
然后根据vtables指向的位置调用vfunc的基本版本或派生版本
在非虚拟情况下,所有这些都不会发生,并且要调用的函数是由编译器在编译时设置的。在编译期间,编译器所能确定的是p
属于“指向基的指针”类型,并将所有p->vfunc()
调用更改为指向地址0x2048