雷火电竞-中国电竞赛事及体育赛事平台

歡迎來到入門教程網!

C語言

當前位置:主頁 > 軟件編程 > C語言 >

簡要解讀C++的動態(tài)和靜態(tài)關聯以及虛析構函數

來源:本站原創(chuàng)|時間:2020-01-10|欄目:C語言|點擊:

C++靜態(tài)關聯與動態(tài)關聯、C++是怎樣實現多態(tài)性的
在現實生活中,多態(tài)性的例子是很多的。我們分析一下人是怎樣處理多 態(tài)性的。例如,新生被錄取人大學,在人學報到時,先有一名工作人員審查材料,他的職責是甄別資格,然后根據錄取通知書上注明的錄取的系和專業(yè),將材料轉到有關的系和專業(yè),辦理具體的注冊人學手續(xù),也可以看作調用不同部門的處理程序辦理入學手續(xù)。在學 生眼里,這名工作人員是總的人口,所有新生辦入學手續(xù)都要經過他。學生拿的是統一的錄取通知書,但實際上分屬不同的系,要進行不同的注冊手續(xù),這就是多態(tài)。那么,這名工 作人員怎么處理多態(tài)呢?憑什么把它分發(fā)到哪個系呢?就是根據錄取通知書上的一個信 息(你被錄取入本校某某專業(yè))??梢姡獏^(qū)分就必須要有相關的信息,否則是無法判別的。

同樣,編譯系統要根據已有的信息,對同名函數的調用作出判斷。例如函數的重載, 系統是根據參數的個數和類型的不同去找與之匹配的函數的。對于調用同一類族中的虛函數,應當在調用時用一定的方式告訴編譯系統,你要調用的是哪個類對象中的函數。例如可以直接提供對象名,如studl.display()或grad1.display()。這樣編譯系統在對程序進行編譯時,即能確定調用的是哪個類對象中的函數。

確定調用的具體對象的過程稱為關聯(binding)。binding原意是捆綁或連接,即把兩樣東西捆綁(或連接)在一起。在這里是指把一個函數名與一個類對象捆綁在一起,建立關聯。一般地說,關聯指把一個標識符和一個存儲地址聯系起來。在計算機字典中可以査到,所謂關聯,是指計算機程序中不同的部分互相連接的過程。有些書中把binding譯為聯編、編聯、束定、或兼顧音和意,稱之為綁定。作者認為:從意思上說,關聯比較確切, 也好理解。但是有些教程中用了聯編這個術語。 大家在看到這個名詞時,應當知道指的就是本節(jié)介紹的關聯。

順便說一句題外話,計算機領域中大部分術語是從外文翻譯過來的,有許多譯名是譯得比較好的,能見名知意的。但也有一些則令人費解,甚至不大確切。例如在某些介紹計算機語言的書籍中,把project譯為“工程”,使人難以理解,其實譯為“項目”比較確切。 有些介紹計算機應用的書中充斥大量的術語,初聽起來好像很唬人、很難懂,許多學習 C++的人往往被大量的專門術語嚇住了,又難以理解其真正含義,不少人“見難而退”。 這個問題成為許多人學習C++的攔路虎。因此,應當提倡用通俗易懂的方法去闡明復雜的概念。其實,有許多看起來深奧難懂的概念和術語,捅破窗戶紙后是很簡單的。建議讀者在初學時千萬不要糾纏于名詞術語的字面解釋上,而要掌握其精神實質和應用方法。

說明:與其他編程語言相比,例如Java、C#等,C++的語法是最豐富最靈活的,同樣也是最難掌握的,大家要循序漸進,莫求速成,在編程實踐中不斷翻閱和記憶。

前面所提到的函數重載和通過對象名調用的虛函數,在編譯時即可確定其調用的虛函數屬于哪一個類,其過程稱為靜態(tài)關聯(static binding),由于是在運行前進行關聯的, 故又稱為早期關聯(early binding)。函數重載屬靜態(tài)關聯。

在調用虛函數時并沒有指定對象名,那么系統是怎樣確定關聯的呢?讀者可以看到,是通過基類指針與虛函數的結合來實現多態(tài)性的。先定義了一個指向基類的指針變量,并使它指向相應的類對象,然后通過這個基類指針去調用虛函數(例如“pt->display()”)。顯然,對這樣的調用方式,編譯系統在編譯該行時是無法確定調用哪一個類對象的虛函數的。因為編譯只作靜態(tài)的語法檢査,光從語句形式(例如“pt->display();”)是無法確定調用對象的。

在這樣的情況下,編譯系統把它放到運行階段處理,在運行階段確定關聯關系。在運行階段,基類指針變量先指向了某一個類對象,然后通過此指針變量調用該對象中的函數。此時調用哪一個對象的函數無疑是確定的。例如,先使pt指向grad1,再執(zhí)行“pt->display()”,當然是調用grad1中的display函數。由于是在運行階段把虛函數和類對象“綁定”在一起的,因此,此過程稱為動態(tài)關聯(dynamic binding)。這種多態(tài)性是動態(tài)的多態(tài)性,即運行階段的多態(tài)性。

在運行階段,指針可以先后指向不同的類對象,從而調用同一類族中不同類的虛函數。由于動態(tài)關聯是在編譯以后的運行階段進行的,因此也稱為滯后關聯(late binding) 。


C++虛析構函數詳解
當派生類的對象從內存中撤銷時一般先調用派生類的析構函數,然后再調用基類的析構函數。但是,如果用new運算符建立了臨時對象,若基類中有析構函數,并且定義了一個指向該基類的指針變量。在程序用帶指針參數的delete運算符撤銷對象時,會發(fā)生一個情況:系統會只執(zhí)行基類的析構函數,而不執(zhí)行派生類的析構函數。

[例] 基類中有非虛析構函數時的執(zhí)行情況。為簡化程序,只列出最必要的部分。

#include <iostream>
using namespace std;
class Point //定義基類Point類
{
public:
  Point( ){} //Point類構造函數
  ~Point(){cout<<"executing Point destructor"<<endl;} //Point類析構函數
};
class Circle:public Point //定義派生類Circle類
{
public:
  Circle( ){} //Circle類構造函數
  ~Circle( ){cout<<"executing Circle destructor"<<endl;} //Circle類析構函數
private:
  int radius;
};
int main( )
{
  Point *p=new Circle; //用new開辟動態(tài)存儲空間
  delete p; //用delete釋放動態(tài)存儲空間
  return 0;
}

這只是一個示意的程序。p是指向基類的指針變量,指向new開辟的動態(tài)存儲空間,希望用detele釋放p所指向的空間。但運行結果為:

executing Point destructor

表示只執(zhí)行了基類Point的析構函數,而沒有執(zhí)行派生類Circle的析構函數。

如果希望能執(zhí)行派生類Circle的析構函數,可以將基類的析構函數聲明為虛析構函數,如:

  virtual ~Point(){cout<<″executing Point destructor″<<endl;}

程序其他部分不改動,再運行程序,結果為:

executing Circle destructor
executing Point destructor

先調用了派生類的析構函數,再調用了基類的析構函數,符合人們的愿望。

當基類的析構函數為虛函數時,無論指針指的是同一類族中的哪一個類對象,系統會采用動態(tài)關聯,調用相應的析構函數,對該對象進行清理工作。

如果將基類的析構函數聲明為虛函數時,由該基類所派生的所有派生類的析構函數也都自動成為虛函數,即使派生類的析構函數與基類的析構函數名字不相同。

最好把基類的析構函數聲明為虛函數。這將使所有派生類的析構函數自動成為虛函數。這樣,如果程序中顯式地用了delete運算符準備刪除一個對象,而delete運算符的操作對象用了指向派生類對象的基類指針,則系統會調用相應類的析構函數。

虛析構函數的概念和用法很簡單,但它在面向對象程序設計中卻是很重要的技巧。

專業(yè)人員一般都習慣聲明虛析構函數,即使基類并不需要析構函數,也顯式地定義一個函數體為空的虛析構函數,以保證在撤銷動態(tài)分配空間時能得到正確的處理。

構造函數不能聲明為虛函數。這是因為在執(zhí)行構造函數時類對象還未完成建立過程,當然談不上函數與類對象的綁定。

上一篇:深入解析C++中類的多重繼承

欄    目:C語言

下一篇:詳解C++編程中多級派生時的構造函數和訪問屬性

本文標題:簡要解讀C++的動態(tài)和靜態(tài)關聯以及虛析構函數

本文地址:http://www.jygsgssxh.com/a1/Cyuyan/2678.html

網頁制作CMS教程網絡編程軟件編程腳本語言數據庫服務器

如果侵犯了您的權利,請與我們聯系,我們將在24小時內進行處理、任何非本站因素導致的法律后果,本站均不負任何責任。

聯系QQ:835971066 | 郵箱:835971066#qq.com(#換成@)

Copyright © 2002-2020 腳本教程網 版權所有