<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 一.繼承中的同名覆蓋 1. **重載** 局限于函數,而且需要通過參數和返回值來區分。 2. **同名覆蓋** 相同的名字出現在不同作用域中。對于函數,則是參數和返回值完全一樣。在繼承的情況下,派生類聲明的同名成員覆蓋基類聲明的同名成員。 >注意,這只是名字的覆蓋,在對象的內存空間中,派生類聲明的同名成員與基類的同名成員仍會占據不同的空間。 3. **同名覆蓋下訪問基類的成員** 可以通過在成員名前加上基類作用域來訪問隱藏的成員。 >[warning] 下面案例可運行在任意編譯器上。 ```c++ #include <iostream> using namespace std; struct Base { int x_; Base(int x) :x_(x) {} }; struct Derived : public Base { int x_; Derived(int x1, int x2) :Base(x1), x_(x2) {} }; int main() { Derived d(2,5); cout<<d.x_<<endl; //派生類同名成員覆蓋基類同名成員 cout<<d.Base::x_<<endl; //訪問基類同名成員 return 0; } ``` >[test] >5 >2 ## 二.虛基類 ### 1.虛基類的功能 >繼承帶來的一系列沖突和冗余問題: >+ 如果一個派生類有多個直接基類,而這些直接基類又有一個共同的基類,則在最終的派生類中會保留該間接共同基類數據成員的多份同名成員。 >+ 在引用這些同名的成員時,必須在成員前增加基類作用域。 虛基類使得在繼承間接共同基類時只保留一份成員,解決數據冗余的問題。 ### 2.虛基類的聲明 在派生類聲明時,為繼承方式中添加 `virtual` 關鍵字。 ### 3.最派生類 含有虛基類的多重繼承體系中,負責對虛基類進行初始化的類。(一般情況下,用 `A` 類創建對象, `A` 就是最派生類。) 當創建一個類類型對象時,編譯器會從這個對象開始,向上查找其繼承關系。如果有虛基類,則非最派生類在構造時,不會對基類進行構造,直到最派生類構造。 如果虛基類沒有無參構造函數,則 **所有直接和間接派生類的構造函數需要在成員初始化器列表中加上虛基類的構造函數** 。但只有最派生類會執行虛基類的構造函數。 ### 4.虛基類的淺層原理 微軟的編譯器(vc6和vs)引入了虛基類表指針。每個對象如果有一個或多個虛基類,就會由編譯器安插一個指針,指向虛基類表。這個虛基類類表是一個數組,它有 `虛基類數目+1` 個元素。第一個元素為虛基類表指針在該派生類的偏移量,后面的元素則是虛基類相對于虛基類表指針位置的偏移量。 其他的編譯器,則可能采用在虛函數表中放入虛基類偏移量的方法。 #### 例1 現在有下面5個類: ```c++ struct A { int x_; A(int x) :x_(x) {} }; struct B1 :virtual public A { int y1_; B1(int x, int y) :A(x), y1_(y) {} }; struct B2 :virtual public A { int y2_; B2() :A(0), y2_(8) {} }; struct C : public B1,public B2 { int z_; C(int x, int y,int z) :A(x),B1(x,y),B2(), z_(z) {} }; struct D : public C { int w_; D(int x, int y,int z,int w_) :A(x),C(x,y,z), w_(z) {} }; ``` 它們的繼承關系樹像這樣: ![](https://img.kancloud.cn/ae/4b/ae4ba7836465537eca224419339b8c02_771x611.png) 當我們構造一個C類的對象,則C類就是最派生類。此時C類對象需要承擔虛基類A的構造。 當我們構造一個D類的對象,則D類就是最派生類。此時D類對象需要承擔虛基類A的構造。 當我們構造一個B1類的對象,則B1類就是最派生類。此時B1類對象需要承擔虛基類A的構造。 當我們構造一個B2類的對象,則B2類就是最派生類。此時B2類對象需要承擔虛基類A的構造。 #### 例2 ```C++ struct A1 { int a; A1(int x=0) : a(x) {} }; struct A2 { int b; A2(int x = 0) : b(x) {} }; struct A3 { int c; A3(int x = 0) : c(x) {} }; struct A4 { int d; A4(int x = 0) : d(x) {} }; struct B :public A2, virtual public A4, public A3, virtual public A1 { int y2_; B(int x = 0) : y2_(x){} }; int main() { return 0; } ``` 使用 `Visual Studio` 打開上述代碼,并在命令行選項中添加 `/d1 reportSingleClassLayoutB `,這樣,在編譯時,通過輸出窗口可以看到 類B的內存布局: ```c class B size(24): +--- 0 | +--- (base class A2) 0 | | b | +--- 4 | +--- (base class A3) 4 | | c | +--- 8 | {vbptr} 12 | y2_ +--- +--- (virtual base A4) 16 | d +--- +--- (virtual base A1) 20 | a +--- B::$vbtable@: 0 | -8 1 | 8 (Bd(B+8)A4) 2 | 12 (Bd(B+8)A1) vbi: class offset o.vbptr o.vbte fVtorDisp A4 16 8 4 0 A1 20 8 8 0 ``` 上面的信息展示出了B的內存布局、虛基類表 `B::$vbtable@` 以及虛基類表的信息 `vbi` 。 在相對位置為 `8` 的位置有一個 `vbptr` ,它是虛基類表指針。再通過看虛基類表中,我們可以看到,第0個元素是虛基類相對于該派生類的偏移量,第1-2個元素則是相應虛基類的偏移量。
                  <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>

                              哎呀哎呀视频在线观看