天天看點

C++ 多态

<b>多态</b>按字面的意思就是多種形态。當類之間存在層次結構,并且類之間是通過繼承關聯時,就會用到多态。

C++ 多态意味着調用成員函數時,會根據調用函數的對象的類型來執行不同的函數。

下面的執行個體中,基類 Shape 被派生為兩個類,如下所示:

#include &lt;iostream&gt;

using namespace std;

class Shape {

protected:

int width, height;

public:

Shape( int a=0, int b=0)

{

width = a;

height = b;

}

int area()

cout &lt;&lt; "Parent class area :" &lt;&lt;endl;

return 0;

};

class Rectangle: public Shape{

Rectangle( int a=0, int b=0):Shape(a, b) { }

int area ()

cout &lt;&lt; "Rectangle class area :" &lt;&lt;endl;

return (width * height);

class Triangle: public Shape{

Triangle( int a=0, int b=0):Shape(a, b) { }

cout &lt;&lt; "Triangle class area :" &lt;&lt;endl;

return (width * height / 2);

// 程式的主函數

int main( )

Shape *shape;

Rectangle rec(10,7);

Triangle tri(10,5);

// 存儲矩形的位址

shape = &amp;rec;

// 調用矩形的求面積函數 area

shape-&gt;area();

// 存儲三角形的位址

shape = &amp;tri;

// 調用三角形的求面積函數 area

當上面的代碼被編譯和執行時,它會産生下列結果:

導緻錯誤輸出的原因是,調用函數 area() 被編譯器設定為基類中的版本,這就是所謂的<b>靜态多态</b>,或<b>靜态連結</b> - 函數調用在程式執行前就準備好了。有時候這也被稱為<b>早綁定</b>,因為 area() 函數在程式編譯期間就已經設定好了。

但現在,讓我們對程式稍作修改,在 Shape 類中,area() 的聲明前放置關鍵字 <b>virtual</b>,如下所示:

virtual int area()

修改後,當編譯和執行前面的執行個體代碼時,它會産生以下結果:

此時,編譯器看的是指針的内容,而不是它的類型。是以,由于 tri 和 rec 類的對象的位址存儲在 *shape 中,是以會調用各自的 area() 函數。

正如您所看到的,每個子類都有一個函數 area() 的獨立實作。這就是<b>多态</b>的一般使用方式。有了多态,您可以有多個不同的類,都帶有同一個名稱但具有不同實作的函數,函數的參數甚至可以是相同的。

<b>虛函數</b> 是在基類中使用關鍵字 <b>virtual</b> 聲明的函數。在派生類中重新定義基類中定義的虛函數時,會告訴編譯器不要靜态連結到該函數。

我們想要的是在程式中任意點可以根據所調用的對象類型來選擇調用的函數,這種操作被稱為<b>動态連結</b>,或<b>後期綁定</b>。

您可能想要在基類中定義虛函數,以便在派生類中重新定義該函數更好地适用于對象,但是您在基類中又不能對虛函數給出有意義的實作,這個時候就會用到純虛函數。

我們可以把基類中的虛函數 area() 改寫如下:

// pure virtual function

virtual int area() = 0;

= 0 告訴編譯器,函數沒有主體,上面的虛函數是<b>純虛函數</b>。