實現多型的四個條件 百度百科

2021-09-06 14:37:01 字數 3993 閱讀 1821

實現多型的四個條件:

1、虛函式

在c++程式設計中,採用關鍵字virtual,虛函式是動態聯編,所以函式型別不能使private,必須是protect或者public型別。

條件所以,實現動態聯編需要三個條件: 

1、 必須把動態聯編的行為定義為類的虛函式。 

2、 類之間存在子型別關係,一般表現為乙個類從另乙個類公有派生而來。 

3、 必須先使用基類指標指向子型別的物件,然後直接或者間接使用基類指標呼叫虛函式。

定義虛函式的限制:(1)非類的成員函式不能定義為虛函式,類的成員函式中靜態成員函式和建構函式也不能定義為虛函式,但可以將析構函式定義為虛函式。實際上,優秀的程式設計師常常把基類的析構函式定義為虛函式。因為,將基類的析構函式定義為虛函式後,當利用delete刪除乙個指向派生類定義的物件指標時,系統會呼叫相應的類的析構函式。而不將析構函式定義為虛函式時,只呼叫基類的析構函式。 

(2)只需要在宣告函式的類體中使用關鍵字「virtual」將函式宣告為虛函式,而定義函式時不需要使用關鍵字「virtual」。 

(3)當將基類中的某一成員函式宣告為虛函式後,派生類中的同名函式自動成為虛函式。 

(4)如果宣告了某個成員函式為虛函式,則在該類中不能出現和這個成員函式同名並且返回值、引數個數、型別都相同的非虛函式。在以該類為基類的派生類中,也不能出現這種同名函式。 

虛函式聯絡到多型,多型聯絡到繼承。所以本文中都是在繼承層次上做文章。沒了繼承,什麼都沒得談。

class a 

執行一下看看結果,喲呵,驀然回首,結果卻是兩個this is a。問題來了,p2明明指向的是class b的物件但卻是呼叫的class a的print()函式,這不是我們所期望的結果,那麼解決這個問題就需要用到虛函式 

class a; 在許多情況下,在基類中不能對虛函式給出有意義的實現,而把它宣告為純虛函式,它的實現留給該基類的派生類去做。這就是純虛函式的作用。 

純虛函式可以讓類先具有乙個操作名稱,而沒有操作內容,讓派生類在繼承時再去具體地給出定義。凡是含有純虛函式的類叫做抽象類。這種類不能宣告物件,只是作為基類為派生類服務。除非在派生類中完全實現基類中所有的的純虛函式,否則,派生類也變成了抽象類,不能例項化物件。

2、覆蓋

覆蓋(override) 

在物件導向的程式設計中,一般出現在繼承(inheritance)。 

當子類宣告了與基類相同名字的方法,而且使用了相同的簽名時,就稱派生類的成員覆蓋(hide)了基類的成員。物件導向程式設計(oop)的三大特性:封裝,繼承,多型!過載overload)和覆蓋都能實現多型,但是真正和多型相關的是覆蓋! (個人愚見:這裡沒有細說,個人感覺虛函式裡的實現的就是包含覆蓋的概念,因為子類和父類的方法名字是一樣的,而父類指標指向子類呼叫方法時會呼叫子類的方法,這不是就相當於覆蓋掉了父類的方法;)

3、過載

過載是可使函式、運算子等處理不同型別資料或接受不同個數的引數的一種方法

過載是不是多型? 

第一種說法

過載是一種是多型(如c++),有四種形式的多型: 

1.虛函式多型 

2模板多型 

3過載 

4轉換 

所謂的動態和靜態區分是另一種基於繫結時間的多型分類,嚴格來說,過載是編譯時多型,即靜態多型,根據不同型別函式編譯時會產生不同的名字如int_foo和char_foo等等,以此來區別呼叫。故過載仍符合多型定義——通過單一標識支援不同特定行為的能力,只是過載屬於靜態多型,而不是通過繼承和虛函式實現的動態多型。 

第二種說法

過載(overload)和多型無關,真正和多型相關的是覆蓋(override)。 

當派生類重新定義了基類的虛擬方法後,基類根據賦給它的不同的派生類引用,動態地呼叫屬於派生類的對應方法,這樣的方法呼叫在編譯期間是無法確定的。因此,這樣的方法位址是在執行期繫結的(動態繫結)。 

過載只是一種語言特性,是一種語法規則,與多型無關,與物件導向也無關。 

不過針對所謂的第二種過載,有乙個專門的名詞--重寫或重定義。過載與重寫的區別就在於是否覆蓋,重寫一般多發生在不同的類且存在繼承關係之間,而過載多是在乙個類裡或者一塊**段裡。

簡介用 abstract 修飾的類是抽象類。

在c++中,含有純虛函式的類稱為抽象類,它不能生成物件。

凡是包含純虛函式的類都是抽象類。

抽象類是不完整的,並且它只能用作基類。它與非抽象類的不同:

1、抽象類不能直接例項化,並且對抽象類使用 new 運算子是編譯時錯誤。雖然一些變數和值在編譯時的型別可以是抽象的,但是這樣的變數和值必須或者為 null,或者含有對非抽象類的例項的引用(此非抽象類是從抽象類派生的)。

2、允許(但不要求)抽象類包含抽象成員。

3、抽象類不能被密封。

當從抽象類派生非抽象類時,這些非抽象類必須具體實現所繼承的所有抽象成員,從而重寫那些抽象成員。在下邊的示例中:

abstract class a

abstract class b: a}

class c: b}

抽象類 a 引入抽象方法 f。類 b 引入另乙個方法 g,但由於它不提供 f 的實現,b 也必須宣告為抽象類。類 c 重寫 f,並提供乙個具體實現。由於 c 中沒有了抽象成員,因此可以(但並非必須)將 c 宣告為非抽象類。

抽象類與介面緊密相關。然介面又比抽象類更抽象,這主要體現在它們的差別上:1)類可以實現無限個介面,但僅能從乙個抽象(或任何其他型別)類繼承,從抽象類派生的類仍可實現介面,從而得出介面是用來解決多重繼承問題的。2)抽象類當中可以存在非抽象的方法,可介面不能且它裡面的方法只是乙個宣告必須用public來修飾沒有具體實現的方法。3)抽象類中的成員變數可以被不同的修飾符來修飾,可介面中的成員變數預設的都是靜態常量(static final)。4)這一點也是最重要的一點本質的一點"抽象類是物件的抽象,然而介面是一種行為規範"。

定義抽象類表示該類中可能已經有一些方法的具體定義,但是介面就僅僅只能定義各個方法的介面(方法名,引數列表,返回型別),並不關心具體細節。

用法1)在繼承抽象類時,必須覆蓋該類中的每乙個抽象方法,而每個已實現的方法必須和抽象類中指定的方法一樣,接收相同數目和型別的引數,具有同樣的返回值,這一點與介面相同。

2)當父類已有實際功能的方法時,該方法在子類中可以不必實現,直接引用的方法,子類也可以重寫該父類的方法(繼承的概念)。

3)而實現 (implement)乙個介面(inte***ce)的時候,是一定要實現介面中所定義的所有方法,而不可遺漏任何乙個。

4)另外,抽象類是不能產生物件的,但可以由它的實現類來宣告物件。

有鑑於此,在實現介面時,我們也常寫乙個抽象類,來實現介面中的某些子類所需的通用方法,接著在編寫各個子類時,即可繼承該抽象類來使用,省去在每個都要實現通用的方法的困擾。

例項為了讓乙個類成為抽象類,至少必須有乙個純虛函式。純虛函式形式如下:

virtual return type function() = 0;

例如,類a有兩個純虛函式lock()、unlock()和乙個虛析構函式:

class a

public:

virtual void lock(void)=0;

virtual void unlock(void)=0;

virtual ~a(void);

將函式lock()和unlock()初始化為0使它們成為純虛函式,沒有0這個初使化器,它們僅僅是虛函式。

class b : public a

protected:

pthread_mutex_t x;

public:

b(void);

~b(void);

virtual void lock(void)

ead_mutex_lock(x);

virtual void unlock(void)        {

ead_mutex_unlock(x);

抽象類對於提供模式、藍圖和後代類遵循的原則有用。如果遵循了藍圖的語義,後代類的行為可能按抽象類提供者和使用者所期望的那樣。通過使用抽象類,c++程式設計師可以提供c++元件的規範,在它的構建中指導元件的實現者。

AnimateWindow 百度百科

animatewindow 開放分類 程式設計 計算機 api 函式功能 該函式能在顯示與隱藏視窗時能產生特殊的效果。有兩種型別的動畫效果 滾動動畫和滑動動畫。函式原型 bool animatewindow hwnd hwnd,dword dwtime,dword dwflags 引數 hwnd 指...

WCF百度百科

根據微軟官方的解釋,wcf 之前的版本名為 indigo 是使用託管 建立和執行面向服務 service oriented 應用程式的統一框架。它使得開發者能夠建立乙個跨平台的安全 可信賴 事務性的解決方案,且能與已有系統相容協作。wcf是微軟分布式應用程式開發的集大成者,它整合了.net平台下所有...

Mashup 百度百科

mashup是糅合,是當今網路上新出現的一種網路現象,將兩種以上使用公共或者私有資料庫的web應用,加在一起,形成乙個整合應用。一般使用源應用的api介面,或者是一些rss輸出 含atom 作為內容源,合併的web應用用什麼技術,則沒有什麼限制。mashup在geek群體和網際網路玩家之中獲得了極大...