多態(tài)按字面的意思就是多種形態(tài)。
當(dāng)類之間存在層次結(jié)構(gòu)负甸,并且類之間是通過(guò)繼承關(guān)聯(lián)時(shí)痹届,就會(huì)用到多態(tài)。
C++ 多態(tài)意味著調(diào)用成員函數(shù)時(shí)带污,會(huì)根據(jù)調(diào)用函數(shù)的對(duì)象的類型來(lái)執(zhí)行不同的函數(shù)香到。
下面的實(shí)例中,基類 Shape 被派生為兩個(gè)類千绪,如下所示:
實(shí)例
#include <iostream>
using namespace std;
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
class Rectangle: public Shape{
public:
Rectangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Rectangle class area :" <<endl;
return (width * height);
}
};
class Triangle: public Shape{
public:
Triangle( int a=0, int b=0):Shape(a, b) { }
int area ()
{
cout << "Triangle class area :" <<endl;
return (width * height / 2);
}
};
// 程序的主函數(shù)
int main( )
{
Shape *shape;
Rectangle rec(10,7);
Triangle tri(10,5);
// 存儲(chǔ)矩形的地址
shape = &rec;
// 調(diào)用矩形的求面積函數(shù) area
shape->area();
// 存儲(chǔ)三角形的地址
shape = &tri;
// 調(diào)用三角形的求面積函數(shù) area
shape->area();
return 0;
}
當(dāng)上面的代碼被編譯和執(zhí)行時(shí)荸型,它會(huì)產(chǎn)生下列結(jié)果:
Parent class area
Parent class area
導(dǎo)致錯(cuò)誤輸出的原因是炸茧,調(diào)用函數(shù) area() 被編譯器設(shè)置為基類中的版本稿静,這就是所謂的靜態(tài)多態(tài)改备,或靜態(tài)鏈接 - 函數(shù)調(diào)用在程序執(zhí)行前就準(zhǔn)備好了蔓倍。有時(shí)候這也被稱為早綁定,因?yàn)?area() 函數(shù)在程序編譯期間就已經(jīng)設(shè)置好了偶翅。
但現(xiàn)在聚谁,讓我們對(duì)程序稍作修改,在 Shape 類中媳搪,area() 的聲明前放置關(guān)鍵字 virtual骤宣,如下所示:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
virtual int area()
{
cout << "Parent class area :" <<endl;
return 0;
}
};
修改后憔披,當(dāng)編譯和執(zhí)行前面的實(shí)例代碼時(shí)爸吮,它會(huì)產(chǎn)生以下結(jié)果:
Rectangle class area
Triangle class area
此時(shí),編譯器看的是指針的內(nèi)容锰霜,而不是它的類型桐早。因此,由于 tri 和 rec 類的對(duì)象的地址存儲(chǔ)在 *shape 中友存,所以會(huì)調(diào)用各自的 area() 函數(shù)陶衅。
正如您所看到的,每個(gè)子類都有一個(gè)函數(shù) area() 的獨(dú)立實(shí)現(xiàn)膨俐。這就是多態(tài)的一般使用方式勇皇。有了多態(tài)敛摘,您可以有多個(gè)不同的類着撩,都帶有同一個(gè)名稱但具有不同實(shí)現(xiàn)的函數(shù),函數(shù)的參數(shù)甚至可以是相同的拖叙。
虛函數(shù)
虛函數(shù) 是在基類中使用關(guān)鍵字 virtual 聲明的函數(shù)。在派生類中重新定義基類中定義的虛函數(shù)時(shí)薯鳍,會(huì)告訴編譯器不要靜態(tài)鏈接到該函數(shù)挖滤。
我們想要的是在程序中任意點(diǎn)可以根據(jù)所調(diào)用的對(duì)象類型來(lái)選擇調(diào)用的函數(shù),這種操作被稱為動(dòng)態(tài)鏈接斩松,或后期綁定惧盹。
純虛函數(shù)
您可能想要在基類中定義虛函數(shù)瞪讼,以便在派生類中重新定義該函數(shù)更好地適用于對(duì)象,但是您在基類中又不能對(duì)虛函數(shù)給出有意義的實(shí)現(xiàn)嫡霞,這個(gè)時(shí)候就會(huì)用到純虛函數(shù)希柿。
我們可以把基類中的虛函數(shù) area() 改寫如下:
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;
};
= 0 告訴編譯器曾撤,函數(shù)沒有主體,上面的虛函數(shù)是純虛函數(shù)盾戴。
代碼鏈接:https://github.com/karst87/cpp/tree/master/learning/com.runoob