MFC第三課 C 特性

2021-05-24 02:00:27 字數 3129 閱讀 8232

首先感謝候俊傑先生與《深入淺出mfc》(第二版),以下心得都來自於對該書的學習~

一、封裝(member variable成員變數、member function成員函式)

把資料宣告為private,不允許外界隨意訪問,只能通過特定的介面來操作,這就是物件導向的封裝(encapsulation)特性。

二、基類與派生類——繼承(inheritance)

問題:基類的函式如何處理派生類對應的不同的資料?答案在於傳入的引數——this指標。(這是乙個隱藏引數)

三、虛函式與多型(polymorphism)

要呼叫父類的函式,你必須使用scope resolution operator(::)明白指出。

結論:①如果以乙個"基類指標"指向乙個"派生類物件",那麼經由此指標,你就只能夠呼叫基類所定義的函式。

②如果你以乙個"派生類指標"指向乙個"基類物件",你必須先做明顯的轉型操作(explict cast),但不提倡。

③如果基類和派生類都定義了"相同名稱的成員函式",那麼通過物件指標呼叫成員函式時,到底呼叫到哪個函式,必須視該指標的原始型別而定。

多型靠虛函式完成。虛函式是對①這條規則反其道而行的設計!

如果你預期派生類有可能重新定義某個成員函式,那麼你就在基類中把此函式設為virtual。

mfc有兩個十分十分重要的虛函式:與document有關的serialize函式和與view有關的ondraw函式,你應該在自己的cmydoc和cmyview中改寫這兩個虛函式。

對於多型,編譯器無法在編譯時期判斷到底是呼叫哪乙個函式,必須在執行期才能判斷,這稱為後期繫結late binding或動態繫結dynamic binding。至於c函式或c++的non-virtual函式,在編譯時期就轉換為乙個固定位址的呼叫了,這稱為前期繫結early binding或靜態繫結static binding。

純虛函式"=0"

純虛函式不需要定義其實際操作,它的存在只是為了在派生類中被重新定義,只是為了提供乙個多型介面。只要是擁有純虛函式的類,就是一種抽象類,它是不能夠被例項化(instantiate)的,也就是說,你不能根據它產生乙個物件。另外,若派生類繼承了基類後沒有改寫基類的純虛函式,那麼該派生類本身也就成了擁有純虛函式的類,即為抽象類。

關於虛函式和多型,還有幾點需要說明:

①如果你期望派生類重新定義乙個成員函式,那麼你應該在基類中把此函式設為virtual。

②抽象類不能產生出物件例項,但是我們可以擁有指向抽象類的指標,以便於操作抽象類的各種派生類。

四、虛函式表(vtable)

每個"內含虛函式的類",編譯器都會為它做出乙個虛函式表,表中的每乙個元素都指向乙個虛函式的位址。此外,編譯器當然也會為類加上一項成員變數,是乙個指向該虛函式表的指標(常被稱為vptr)。(關於c++類的成員函式,你並沒有在class物件的記憶體區塊中看到與成員函式有關的任何東西。)

虛函式表的內容是依據類中的虛函式宣告次序,一一填入函式指標。

派生類會繼承基類的虛函式表(以及所有其它可以繼承的成員)。當我們在派生類中改寫虛函式時,虛函式表就受了影響:表中元素所指的函式位址將不再是基類的函式位址,而是派生類的函式位址。

五、靜態成員(變數與函式)

不要把static成員變數的初始化操作安排在類的建構函式中,因為建構函式可能一再被呼叫,而變數的初值卻只應該設定一次。也不要把初始化操作安排在標頭檔案中,因為它可能會被載入許多地方,因此也就可能被執行許多次。

設定static成員變數初值時,不受任何訪問許可權的束縛。

由於static成員函式不需要借助任何物件,就可以被呼叫執行,所以編譯器不會為它暗加乙個this指標。也因此,static成員函式無法處理類之中的non-static成員變數。

六、建構函式與析構函式

c++的new運運算元和c的malloc函式都是用於配置記憶體,但前者比之後者的優點是,new不但配置物件所需的記憶體空間,同時會引發建構函式的執行。

乙個有著層次結構的類群組,當派生類的物件誕生之時,建構函式的執行是由最基類(most based)至最尾端派生類(most derived);當物件要毀滅之前,析構函式的執行則是反其道而行。

在c++中,有四種方法可以產生乙個物件:

①在堆疊(stack)之中產生;

②在堆(heap)中產生;

③產生乙個全域性物件(同時也必然是個靜態物件);

④產生乙個區域性靜態物件。

當編譯器編譯你的程式,發現乙個靜態物件時,它會把這個物件加到乙個鍊錶中。更精確的說法是,編譯器不只是加上此靜態物件,它還加上乙個指標,指標物件之建構函式及其引數。把控制權交給程式進入點(main或winmain)之前,startup**會快速在該鍊錶上移動,呼叫所有登記在案的建構函式並使用登記在案的引數,於是就初始化了你的靜態物件。

七、執行時型別識別(rtti)

runtime type information

八、異常處理(exception handling)

c++的exception基本上是與c的setjmp和longjmp函式對等的東西,但它增加了一些功能,以處理c++程式的特別需求。從多層巢狀的例程呼叫中直接以一條快捷方式撤回到異常情況處理例程(exception handler),這種"錯誤管理方式"遠比結構化程式中經過層層的例程傳回一系列的錯誤狀態來得好。

c++匯入了三個新的exception保留字:try、catch、throw

九、template

c++的template有兩種:一種針對function,另一種針對class。

template函式的資料型別引數t幾乎可以適應"任何資料型別",但函式中對該型別數值的任何運算操作,都必須支援。

編譯器遇到乙個template時,不能夠立刻為它產生機器**,它必須等待,直到template被指定某種型別。

有乙個常用的技術,borland稱之為smart(在鏈結過程中,所有重複的部分將被刪除),應該算是最容易的:每乙個使用template的程式**的目的檔案中都存在有template**,鏈結器負責複製和刪除。

python第三課答案 python第三課

字串操作 s alexwusir s1 s.capitalize 首字母大寫 print s1 全大寫,全小寫 s2 s.upper s21 s.lower print s2,s21 大小寫翻轉 s3 s.swapcase print s3 每個隔開 特殊字元或數字 的單詞首字母大寫 s alex ...

python第三課答案 python第三課筆記

以下哪個變數的命名不正確?為什麼?a mm 520 b mm520 c 520 mm d 520 mm 答 c不正確,不能數字開頭 在不上機的情況下,以下 你能猜到螢幕會列印什麼內容嗎?myteacher 小甲魚 yourteacher myteacher yourteacher 黑夜 print ...

python第三課答案 python第三課

1.迴圈物件,主要呼叫next 2.迭代器iterator 在理解上可以和迴圈物件理解為乙個東西。3.生成器 generator 自定義的迴圈物件。4.表推導 list comprehension 是快速生成表的方法。表推導用中括號。l x 2 for x in range 10 練習 f open...