虛函數的使用

虛函數的使用:
目的:為了讓類的指針和類的對象可以調用到想調用到函數;
原理:
1 虛函數:virtual func();
2 有一個以上虛函數的類都會隱藏的有一個成員變量:ptr_vtable(指向vtable的指針)
3 vtable用來存儲虛函數的指針的表;
4 在構造函數的時候會初始化ptr_vtable;(所以不會有虛構造函數)
代碼解析:

#include <iostream>
 
class A
{
public:
     void func1()
     {
          std::cout << "func1 in A" << std::endl;
     }
 
     virtual void func2()
     {
          std::cout << "func2 in A" << std::endl;
     }
     virtual ~A()
     {
          std::cout << " ~ A" << std::endl;
     }
};
 
class B : public A
{
public:
     void func1()
     {
          std::cout << "func1 in B" << std::endl;
     }
 
     void func2()
     {
          std::cout << "func2 in B" << std::endl;
     }
     ~B()
     {
          std::cout << " ~ B" << std::endl;
     }
};
 
class C final:public B
{
public:
     void func1 ()
     {
          std::cout << "func1 in C" << std::endl;
     }
 
     void func2 () override
     {
          std::cout << "func2 in C" << std::endl;
     }
     ~C()
     {
          std::cout << " ~ C" << std::endl;
     }
};
 
int main(int argc, char *argv[]) {
 
     A* ptr = new C();
     ptr->func1();  // func1 in A
     ptr->func2();  // func2 in B
     delete ptr;
 
     return 0;
}

用類A的變量調用到B到對象時,只有基類中的虛函數才會對應到想調用的函數。
分析:在B的對象構造的時候,會先構造A,這樣就會有vtable,然後構造B的時候,發現有新的func2,
就會更新vtable中func2的地址,所以調用func2的時候,是通過vtable調用的。
深入提問:那麼為什麼func1調用的是A的,而不是B的呢?

進一步:為什麼析構函數要聲明為虛函數?
當A的析構函數被聲明為虛函數的時候,那麼B繼承A後,虛解構函數會指向B的解構函數,這樣就可以
解構到B(真正指向的對象類型)。
深入提問:為什麼A的virtual func2 不會被調用,而A的virtual ~A會被調用?

編譯原理:
1 靜態編譯:編譯時綁定,即是函數調用的地方會替換為響應的函數的定義。(運行更快)
2 動態編譯:運行時綁定,即是該函數調用的時候是在運行的時候,會調用相應的函數。(更加動態)
所以,當動態編譯出問題的時候,我們是無法在編譯階段看出來的,這樣就需要確保動態編譯是我們
想要的,這也是下面這個關鍵字的原因。

進一步:override
Override:專門為子類設計的,要覆蓋父的virtual函數用的,確保會替換父類的虛函數。

Final關鍵字:聲明這個類無法被繼承。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值