多型的這個概念稍微有點模糊,如果想在一開始就想用清晰用語言描述它,讓讀者能夠明白,似乎不太現實,所以我們先看如下**:
//例程1#include
using
namespace std;
class vehicle
void showmember()
;
class car:public vehicle
void showmember()
;
void
main()
在c++中是允許派生類過載基類成員函式的,對於類的過載來說,明確的,不同類的物件,呼叫其類的成員函式的時候,系統是知道如何找到其類的同名成員,上面**中的a.showmember();,即呼叫的是vehicle::showmember(),b.showmember();,即呼叫的是car::showmemeber();。
但是在實際工作中,很可能會碰到物件所屬類不清的情況,下面我們來看一下派生類成員作為函式引數傳遞的例子,**如下:
//例程2#include
using
namespace std;
class vehicle
void showmember()
;
class car:public vehicle
void showmember()
;
void test(vehicle &temp)
void
main()
例子中,物件a與b分別是基類和派生類的物件,而函式test的形參卻只是vehicle類的引用,按照類繼承的特點,系統把car類物件看做是乙個vehicle類物件,因為car類的覆蓋範圍包含vehicle類,所以test函式的定義並沒有錯誤,我們想利用test函式達到的目的是,傳遞不同類物件的引用,分別呼叫不同類的,過載了的,showmember成員函式,但是程式的執行結果卻出乎人們的意料,系統分不清楚傳遞過來的基類物件還是派生類物件,無論是基類物件還是派生類物件呼叫的都是基類的showmember成員函式。
為了要解決上述不能正確分辨物件型別的問題,c++提供了一種叫做多型性(polymorphism)的技術來解決問題,對於例程式1,這種能夠在編譯時就能夠確定哪個過載的成員函式被呼叫的情況被稱做先期聯編(early binding),而在系統能夠在執行時,能夠根據其型別確定呼叫哪個過載的成員函式的能力,稱為多型性,或叫滯後聯編(late binding),下面我們要看的例程3,就是滯後聯編,滯後聯編正是解決多型問題的方法。
**如下:
//例程3#include
using
namespace std;
class vehicle
virtual
void showmember()//
虛函式;
class car:public vehicle
virtual
void showmember()//
虛函式,
在派生類中,由於繼承的關係,這裡的
virtual
也可以不加
; void test(vehicle &temp)
intmain()
多型特性的工作依賴虛函式的定義,在需要解決多型問題的過載成員函式前,加上virtual關鍵字,那麼該成員函式就變成了虛函式,從上例**執行的結果看,系統成功的分辨出了物件的真實型別,成功的呼叫了各自的過載成員函式。
多型特性讓程式設計師省去了細節的考慮,提高了開發效率,使**大大的簡化,當然虛函式的定義也是有缺陷的,因為多型特性增加了一些資料儲存和執行指令的開銷,所以能不用多型最好不用。
虛函式的定義要遵循以下重要規則:
1.如果虛函式在基類與派生類**現,僅僅是名字相同,而形式引數不同,或者是返回型別不同,那麼即使加上了virtual關鍵字,也是不會進行滯後聯編的。
2.只有類的成員函式才能說明為虛函式,因為虛函式僅適合用與有繼承關係的類物件,所以普通函式不能說明為虛函式。
3.靜態成員函式不能是虛函式,因為靜態成員函式的特點是不受限制於某個物件。
4.內聯(inline)函式不能是虛函式,因為內聯函式不能在執行中動態確定位置。即使虛函式在類的內部定義,但是在編譯的時候系統仍然將它看做是非內聯的。
5.建構函式不能是虛函式,因為構造的時候,物件還是一片未定型的空間,只有構造完成後,物件才是具體類的例項。
6.析構函式可以是虛函式,而且通常聲名為虛函式。
說明一下,雖然我們說使用虛函式會降低效率,但是在處理器速度越來越快的今天,將乙個類中的所有成員函式都定義成為virtual總是有好處的,它除了會增加一些額外的開銷是沒有其它壞處的,對於保證類的封裝特性是有好處的。
對於上面虛函式使用的重要規則6,我們有必要用例項說明一下,為什麼具備多型特性的類的析構函式,有必要宣告為
virtual。
**如下:
#include
"stdafx.h"
#include
using
namespace
std;
class
vehicle
public:
vehicle(float
speed,int
total)
vehicle::speed=speed;
vehicle::total=total;
virtual
void
showmember()
cout
<<<"|"
< cout <<" 載入vehicle 基類析構函式 " protected: float speed; inttotal; class car:public vehicle public: car(int aird,float speed,int total):vehicle(speed,total) car::aird=aird; virtual void showmember() cout <<<"|" <<<"|" < cout <<" 載入car 派生類析構函式 " protected: intaird; void test(vehicle &temp) temp.showmember(); void delpn(vehicle *temp) delete temp; void main() car *a=new car(100,1,1); a->showmember(); delpn(a); cin.get(); 從上例**的執行結果來看,當呼叫delpn(a);後,在析構的時候,系統成功的確定了先呼叫car類的析構函式,而如果將析構函式的virtual修飾去掉,再觀察結果,會發現析構的時候,始終只呼叫了基類的析構函式,由此我們發現,多型的特性的virtual修飾,不單單對基類和派生類的普通成員函式有必要,而且對於基類和派生類的析構函式同樣重要。 類的多型特性是支援物件導向的語言最主要的特性,有過非物件導向語言開發經歷的人,通常對這一章節的內容會覺得不習慣,因為很多人錯誤的認為,支援類的封裝的語言就是支援物件導向的,其實不然,visual basic 6.0 是典型的非物件導向的開發語言,但是它的確是支援類,支援類並不能說明就是支援物件導向,... c 中類的多型與虛函式的使用 類的多型特性是支援物件導向的語言最主要的特性,有過非物件導向語言開發經歷的人,通常對這一章節的內容會覺得不習慣,因為很多人錯誤的認為,支援類的封裝的語言就是支援物件導向的,其實不然,visual basic 6.0是典型的非物件導向的開發語言,但是它的確是支援類,支援類... 多型的這個概念稍微有點模糊,如果想在一開始就想用清晰用語言描述它,讓讀者能夠明白,似乎不太現實,所以我們先看如下 例程 include using namespace std class vehicle void showmember class car public vehicle void sh...C 中類的多型與虛函式的使用
C 中類的多型與虛函式的使用
C 中類的多型與虛函式的使用