Animal类有一个虚函数makeSound(),它被Cat和Dog类继承并覆盖了该函数以实现不同的行为。当使用Animal指针或引用调用makeSound()函数时,会根据运行时对象的类型来动态地决定调用哪个子类的函数,从而实现多态性。 1.2、为什么需要虚函数? 虚函数可以让子类对象在运行时动态地继承和修改父类的成员函数,使得代码更加灵活...
所以这时候虚函数指针指向的是基类的虚函数表。 (例如此代码中,使用强制转换,依然调用了基类的func()) 虚函数实现的过程就是如此 综上所述,通俗的过程即是: 在调用虚函数时,编译器通过该对象的虚函数指针来访问该对象实际所属类的虚函数表,然后调用虚函数的内容。 (虚函数指针和虚函数表的概念在上方有介绍) ...
在这种情况下,虽然将objDerived传递给了objBase,进而被解读成一个Base实例,但该实例的VFT指针仍然指向Derived类的虚函数表,因此通过该VFT执行的是Derived::Func1.虚函数表就是通过上面的方式来实现C++的多态。 要验证虚函数表的存在其实也很简单,可以通过比较同一个类,一个包含虚函数,一个不包含,对比其大小就知道...
如果一个类中含有虚函数,那么为了实现动态绑定,编译器会在原来的代码中插入(augment)一个新的成员变量--一个成员指针vptr, 这个指针指向一张包含所有虚函数的函数指针表vtable. 当我们调用虚函数时,实际上是通过vptr这个指针来调用函数指针表vtable里面的某个函数指针来实现函数调用。 一般而言,这张vtable会在数据段,...
虚函数表vtable vtable可以看成一个数组,其元素类型为函数指针: int (*p[])(...); 对应的LLVM IR: i32 (...)** 对应的生成代码: PointerType* createVtable() { // function type: int (*f)(...) => i32 (...) FunctionType *funcType = FunctionType::get(Builder->getInt32Ty(), {}, ...
虚函数实现原理: 一个含有虚函数的类都有至少一个虚函数表,里面存放着该类所有虚函数的指针。 类的所有对象都共享类的虚函数表,这些对象都有一个或多个虚函数表指针来指向一个或多个虚函数表。 子类继承父类时也会继承父类的虚函数表,但父类的虚函数表和子类继承过来的虚函数表是两个独立的表。
在上面的例子中,我们使用基类指针s来访问Circle类的对象,因为Circle类重写了draw()函数,所以调用的是Circle类中的实现。这种行为称为运行时多态性,因为实际调用的函数是在运行时确定的。 多态的底层原理 在C++中,多态是通过虚函数表和虚指针来实现的。虚函数表是一个特殊的表格,其中包含了虚函数的地址。每个类都有...
虚函数 在这之前,我们先聊聊虚函数。虚就是代表不是真实的,可以灵活的,函数就是方法,虚函数就是用不同的策略实现共同的方法。虚函数是在基类中被声明为virtual,并在派生类中...
这和虚函数的实现机制有关,虚函数是通过虚函数表来实现的virtual method table (VMT)。当在函数中声明虚函数以后,编译器会在对象中添加一个隐含的成员变量指向类中虚函数指针数组的首地址。一个类只有一个虚表,类的多个对象公用一个虚表,但是每个类的对象中会有一个指向虚表的指针(*__vptr)。
每一个含有虚函数(无论是其本身就含有的,还是从基类继承过来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针。如下图所示 : 其中: B的虚函数表中存放着B::foo和B::bar两个函数指针 D的虚函数表中存放的既有继承自B的虚函数B::foo,又有重写了基类虚函数B::bar的D:...