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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## 4.4 多態 (Polymorphism) 為了能更好的理解本節內容,你需要清楚的知道怎樣使用指針pointers 和類之間的繼承 inheritance between classes。建議如果你覺得以下這些表達式比較生疏的的話, 請復習指定的章節: ~~~ int a::b(c) {}; // 類Classes (Section 4.1) ~~~ ~~~ a->b // 指針和對象pointers and objects (Section 4.2) ~~~ ~~~ class a: public b; // 類之間的關系Relationships between classes (Section 4.3) ~~~ ### 基類的指針(Pointers to base class) 繼承的好處之一是**一個指向子類(derived class)的指針與一個指向基類(base class)的指針是type-compatible的。** 本節就是重點介紹如何利用C++的這一重要特性。例如,我們將結合C++的這個功能,重寫前面小節中關于長方形rectangle 和三角形 triangle 的程序: | // pointers to base class ~~~ #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void) { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << rect.area() << endl; cout << trgl.area() << endl; return 0; } ~~~ | 20 10 | 在主函數 main 中定義了兩個指向class CPolygon的對象的指針,即 *ppoly1 和 *ppoly2。 它們被賦值為rect 和 trgl的地址,因為rect 和 trgl是CPolygon 的子類的對象,因此這種賦值是有效的。 使用*ppoly1 和 *ppoly2 取代rect 和trgl 的唯一限制是*ppoly1 和 *ppoly2 是CPolygon* 類型的,因此我們只能夠引用CRectangle 和 CTriangle 從基類CPolygon中繼承的成員。正是由于這個原因,我們不能夠使用*ppoly1 和 *ppoly2 來調用成員函數 area(),而只能使用rect 和 trgl來調用這個函數。 要想使CPolygon 的指針承認area()為合法成員函數,必須在基類中聲明它,而不能只在子類進行聲明(見下一小節)。 ### 虛擬成員(Virtual members) 如果想在基類中定義一個成員留待子類中進行細化,我們必須在它前面加關鍵字virtual ,以便可以使用指針對指向相應的對象進行操作。 請看一下例子: | // virtual members ~~~ #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) { return (0); } }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void) { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; CPolygon poly; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; CPolygon * ppoly3 = &poly; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly3->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; cout << ppoly3->area() << endl; return 0; } ~~~ | 20 10 0 | 現在這三個類(CPolygon, CRectangle 和 CTriangle) 都有同樣的成員:width, height, set_values() 和 area()。 area() 被定義為virtual 是因為它后來在子類中被細化了。你可以做一個試驗,如果在代碼種去掉這個關鍵字(virtual),然后再執行這個程序,三個多邊形的面積計算結果都將是 0 而不是20,10,0。這是因為沒有了關鍵字virtual ,程序執行不再根據實際對象的不用而調用相應area() 函數(即分別為CRectangle::area(), CTriangle::area() 和 CPolygon::area()),取而代之,程序將全部調用CPolygon::area(),因為這些調用是通過CPolygon類型的指針進行的。 因此,關鍵字virtual 的作用就是在當使用基類的指針的時候,使子類中與基類同名的成員在適當的時候被調用,如前面例子中所示。 **注意**,雖然本身被定義為虛擬類型,我們還是可以聲明一個CPolygon 類型的對象并調用它的area() 函數,它將返回0 ,如前面例子結果所示。 ### 抽象基類(Abstract base classes) 基本的抽象類與我們前面例子中的類CPolygon 非常相似,唯一的區別是在我們前面的例子中,我們已經為類CPolygon的對象(例如對象poly)定義了一個有效地area()函數,而在一個抽象類(abstract base class)中,我們可以對它不定義,而簡單得在函數聲明后面寫 =0 (等于0)。 類CPolygon 可以寫成這樣: // abstract class CPolygon ~~~ class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; }; ~~~ 注意我們是如何在virtual int area (void)加 =0 來代替函數的具體實現的。這種函數被稱為純虛擬函數(pure virtual function),而所有包含純虛擬函數的類被稱為抽象基類(abstract base classes)。 抽象基類的最大不同是它不能夠有實例(對象),但我們可以定義指向它的指針。因此,像這樣的聲明: `CPolygon poly;` 對于前面定義的抽象基類是不合法的。 然而,指針: `CPolygon * ppoly1; CPolygon * ppoly2` 是完全合法的。這是因為該類包含的純虛擬函數(pure virtual function) 是沒有被實現的,而又不可能生成一個不包含它的所有成員定義的對象。然而,因為這個函數在其子類中被完整的定義了,所以生成一個指向其子類的對象的指針是完全合法的。 下面是完整的例子: | // virtual members ~~~ #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void) { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); cout << ppoly1->area() << endl; cout << ppoly2->area() << endl; return 0; } ~~~ | 20 10 | 再看一遍這段程序,你會發現我們可以用同一種類型的指針(CPolygon*)指向不同類的對象,至一點非常有用。 想象一下,現在我們可以寫一個CPolygon 的成員函數,使得它可以將函數area()的結果打印到屏幕上,而不必考慮具體是為哪一個子類。 | // virtual members ~~~ #include <iostream.h> class CPolygon { protected: int width, height; public: void set_values (int a, int b) { width=a; height=b; } virtual int area (void) =0; void printarea (void) { cout << this->area() << endl; } }; class CRectangle: public CPolygon { public: int area (void) { return (width * height); } }; class CTriangle: public CPolygon { public: int area (void) { return (width * height / 2); } }; int main () { CRectangle rect; CTriangle trgl; CPolygon * ppoly1 = &rect; CPolygon * ppoly2 = &trgl; ppoly1->set_values (4,5); ppoly2->set_values (4,5); ppoly1->printarea(); ppoly2->printarea(); return 0; } ~~~ | 20 10 | 記住,this 代表代碼正在被執行的這一個對象的指針。 抽象類和虛擬成員賦予了C++ 多態(polymorphic)的特征,使得面向對象的編程object-oriented programming成為一個有用的工具。這里只是展示了這些功能最簡單的用途。想象一下如果在對象數組或動態分配的對象上使用這些功能,將會節省多少麻煩。
                  <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>

                              哎呀哎呀视频在线观看