多态性,虛函數與純虛函數(複習幹貨)
向對象發送同一個消息,不同的對象在接收時會産生不同的
行為(即方法,屬于本對象的行為)。
- 多态分為靜态多态性和動态多态性。
- 靜态多态性,函數重載和運算符重載都屬于靜态多态性。
- 動态多态性,通過虛函數實作。
-
靜态多态性:編譯階段确定函數位址(位址早綁定)。
函數調用速度快,效率高,但是缺乏靈活性。
動态多态性:運作階段确定函數位址(位址晚綁定)。
利用虛函數實作動态多态性
- 所謂虛函數,就是在基類中聲明函數是虛拟的,并不是實際存在的函數,然後在派生類中才正式定義此函數。
- 虛函數實作的動态多态性就是:同一類族中不同類的對象,對同一函數調用作出不同的響應。
- 虛函數
- 基類中聲明(virtual),在類外定義虛函數不必在函數名前加virtual,函數體可以是空,它的作用隻是定義了一個虛函數名,具體功能留給派生類去添加實作。
- 在派生類中聲明時,virtual可以寫,也可以不寫,但習慣性一般在每一層聲明該函數時都加virtual,使程式更加清晰。
- 在派生類中重新定義此虛函數,函數類型,函數名,函數參數個數及參數類型必須與基類的虛函數相同。
-
虛函數的作用是允許在派生類中重新定義與基類同名的函數,并且可以通過基類指針或引用來通路基類和派生類中的同名函數。
Base類.h檔案
#include<iostream>
usaing namespace std;
class Base
{
public:
Base(int a, int b){ this->a = a; this->b = b;}
virtual void display();
private:
int a;
int b;
};
基類.cpp檔案
#include"Base.h"
void Base::dispaly()
{
cout<<"我是基類"<<endl;
cout<<"a="<<a<<"\t"<<"b="<<b<<endl;
// 可以是空
}
派生類.h檔案
#include"Base.h"
class Son :
public Base
{
public:
Son(int a, int b, int c):Base(a,b){this->c = c;}
virtual void display();
private:
int c;
};
派生類 .cpp檔案
#include"Son.h"
void Son::display()
{
cout<<"我是Son的虛函數"<<endl;
cout<<"a = "<<a<<"\tb="<<b<<"\tc="<<c<<endl;
}
main函數
#include"Son.h"
int main()
{
Son s(1,2,3);
Base *p = s;
p->display();
return 0;
}
運作結果:
我是Son的虛函數
a=1 b=2 c=3
純虛函數
-
什麼是抽象類?
凡是包含純虛函數的類都是抽象類。由于它常作為基類,通常稱為抽象基類。因為純虛函數是不能被調用的,包含純虛函數的類是無法建立對象的(可以建立基類的指針或引用),抽象類的作用是作為一個類族的共同基類,或者說,為一個類族提供一個公共接口。(頂部可以有好幾層都是抽象類)
- 靜态成員函數不能定義為虛函數,也不能定義成純虛函數。
- 定義這些抽象類的唯一目的是用它作為基類去建立派生類。
-
什麼是具體類?
在抽象類所派生的新類中對基類的所有純虛函數進行定義,那麼這些函數就被賦予了功能,可以被調用,這個派生類就不是抽象類,而是可以定義對象的具體類。
- 如果在派生類中沒有對所有純虛函數進行定義,則此派生類仍然是抽象類,不能定義對象。
- 當派生類成為具體類後,就可以用基類指針指向派生類對象,用指針調用虛函數,實作多态。
- 派生類對基類的純虛函數進行定義後,該函數就成為了虛函數,而不是純虛函數。
-
純虛函數聲明: virtual 函數類型 函數名 (參數清單) = 0;
隻需要聲明,不需要在基類具體實作。
聲明如下:
virtual void display() = 0;
- 派生類中必須與基類擁有相同的函數類型,函數名,參數個數以及參數類型。
基類 .h檔案
#include<iostream>
using namespace std;
class Shape
{
public:
virtual double area() = 0;
virtual void display() = 0;
};
派生類 .h檔案
#include "Shape.h"
class Triangle :
public Shape
{
//三角形
public:
Triangle(int side, int high) { this->side = side; this->high = high; }
virtual double area();
virtual void display();
private:
int side;
int high;
};
派生類 .cpp檔案
#include "Triangle.h"
double Triangle::area()
{
return (double)side * high * (1.0/2);
}
void Triangle::display()
{
all_area += area();
cout << "Triangle的面積是:" << area() << endl;
}
main函數
#include"Triangle.h"
int main()
{ Triangle e(2, 4);
Shape* pt;
pt = &e;
pt->display();
運作結果:
Triangle的面積是:4