<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                ## 一.虛函數 ### 1.作用 允許在派生類中重新定義與基類同名的函數,并且通過 **基類指針或引用** 來訪問派生類中與基類同名的函數。 ### 2.虛函數的定義聲明 在基類 `A` 聲明時,在函數名 `f` 前添加 `virtual` 關鍵字。 此時若有派生類 `B` 繼承了 `A` 類,則與基類同名的函數 `f` 會自動加上 `virtual` 關鍵字。 #### 例1 使用虛函數與不使用虛函數的案例對比 不使用虛函數: ```c++ #include <iostream> using namespace std; struct A { //這不是虛函數哦 void hi() { cout << "Hi, A" <<endl; } }; struct B :public A { //這不是虛函數哦 void hi() { cout << "Hi, B" <<endl; } }; int main() { B b; A &ra = b; b.hi(); ra.hi(); return 0; } ``` >[test] >Hi, B >Hi, A 使用虛函數: ```c++ #include <iostream> using namespace std; struct A { //虛函數 virtual void hi() { cout << "Hi, A" <<endl; } }; struct B :public A { //虛函數 void hi() { cout << "Hi, B" <<endl; } }; int main() { B b; A &ra = b; b.hi(); ra.hi(); return 0; } ``` >[test] >Hi, B >Hi, B #### 例2 虛析構函數 當我們使用基類指針去接收一個動態創建的派生類對象時,直接 `delete` 基類指針,則只會執行基類的析構函數,而不會刪除派生類新增部分。這就會產生內存垃圾: ```c++ #include <iostream> using namespace std; struct A { ~A() { cout << "析構 A" <<endl; } }; struct B :public A { ~B() { cout << "析構 B" <<endl; } }; int main() { A *pa = new B; delete pa; return 0; } ``` >[test] >析構 A 為了避免這個問題,我們一般把析構函數聲明虛函數,即使析構函數是空的: ```c++ #include <iostream> using namespace std; struct A { //虛析構函數 virtual ~A() { cout << "析構 A" <<endl; } }; struct B :public A { //虛析構函數 ~B() { cout << "析構 B" <<endl; } }; int main() { A *pa = new B; delete pa; return 0; } ``` >[test] >析構 B >析構 A >[warning]不可以將構造函數設置為虛函數,因為構造函數執行完畢后,對象創建才算完成,沒有對象,就不能完成匹配。 ### 3.通過虛函數實現動態聯編的條件 + 虛函數 + 通過 **基類指針或引用** 訪問派生類對象 如果直接通過派生類、派生類的指針、派生類的引用、作用域運算符(包括基類和派生類)來訪問與基類同名的函數,則只進行 **靜態聯編** 。 ### 4.虛函數的實現原理 編譯器會為每個含有虛函數的類提供一個虛函數表(vtable),它實際上就是一個函數指針數組,用于存放該類中所有虛函數的入口地址;而每當用多態類創建一個對象時,編譯器就會自動生成一個虛函數表指針(vptr),由構造函數正確對其初始化,使其指向該對象所屬類的虛函數表,最后將它放置在對象結構的開頭。 虛函數表中的函數地址可能并不是真正的虛函數地址,而可能是中間過渡函數 `thunk` 的地址,而這個中間過渡函數用于跳轉到虛函數的真實地址,并對傳入的對象指針 `this` 進行調整。 #### 例3 假設有以下類的聲明: ```c++ struct A1 { int x_; A1(int x = 1) :x_(x) {} }; struct A2 { int x_; A2(int x = 2) :x_(x) {} virtual void test() { cout << "Call base A2 vf"; } }; struct A3 { int x_; A3(int x = 3) :x_(x) {} virtual void test() { cout << "Call base A3 vf"; } }; struct B : public A1, public A2, public A3 { int y_; void test() { cout << "Call derived vf"; } }; ``` 使用 `Visual Studio` 打開上述代碼,并在命令行選項中添加 `/d1 reportSingleClassLayoutB `,這樣,在編譯時,通過輸出窗口可以看到 類 `B` 的內存布局和虛函數表: ``` class B size(24): +--- 0 | +--- (base class A2) 0 | | {vfptr} 4 | | x_ | +--- 8 | +--- (base class A3) 8 | | {vfptr} 12 | | x_ | +--- 16 | +--- (base class A1) 16 | | x_ | +--- 20 | y_ +--- B::$vftable@A2@: | &B_meta | 0 0 | &B::test B::$vftable@A3@: | -8 0 | &thunk: this-=8; goto B::test B::test this adjustor: 0 ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看