从虚拟函数调用派生类的成员

Calling member of Derived class from virtual function

本文关键字:成员 派生 虚拟 函数调用      更新时间:2023-10-16

我对虚拟函数有点困惑。

让我们假设您有一个带有虚拟函数foo()的基类,然后该函数在派生类中被重写

   class Baseclass
   {  
   public:
       virtual void foo()
       {
           //...
       }
   };
   class Derived: public BaseClass
   {
   private:
       int member_val;
   public:
       Derived( int init )
           : member_val( init )
       {}
       void foo()
       {
           member_val++;
       }
   };

和使用派生类的成员值的foo,当我编写此代码时

Derived d( 10 );
Base* bPtr = &d;
bPtr->foo(); 

foo()调用了Derived类,因为_vptr指向"Derived class virtual table",而"Deriveed class virtual table"中的指针指向Derived类中的foo(。我们把它称为Base*(这是Base类型),但要找到member_val,我们需要Derived*(这个Derived类型)。那么它是如何在引擎盖下工作的呢?

正确的问题是一半的答案。就像在您的案例中一样,您询问this传递给Derived::foo()的是什么,答案是"相同"。您创建了一个类为Derived的对象。它在内存中的分配方式如下:

Derived:
--------
vptr_t* vptr
int member_val

然后将&d强制转换为Derived*Base*。指针怎么了?没有什么它只是改变了它的类型,而不是它所指向的实际地址。然后可以使用dynamic_cast<Derived*>()甚至static_cast<Derived*>将它转换回Derived*。在这种情况下,两者都使用是绝对安全的。

因此,唯一实际的问题是虚拟函数表是如何工作的?但这是另一个问题,你似乎明白了

请注意:当几个基类一个接一个地位于内存中时,多重继承会使事情变得更加复杂。