類之間的相互引用以及如何避免類之間的迴圈依賴

2021-09-21 02:12:14 字數 2455 閱讀 5451

在分析類的相互引用之前,我們需要了解乙個程式的整個執行過程。

整合開發環境(ide)整合了編輯器、編譯器、鏈結器,除錯、部署等功能,我們在編輯器裡寫好的c/c++檔案一開始以ascii字符集儲存在硬碟裡,計算機只能識別機器語言(二進位制指令,又稱bcd碼),為此,編譯器的功能是將寫好的原始檔(c/c++)按照一定的對應規則對映成計算機能夠識別的二進位制指令,也就是我們常說的編譯過程。

編譯是指把文字形式源**翻譯為機器語言形式的目標檔案(windows下是.obj,linux下是.o的二進位制檔案)的過程。

鏈結是把目標檔案、作業系統的啟動**、以及用到的庫檔案進行組織,形成最終可執行的exe檔案。

首先分析c/c++程式的整個執行過程:

編譯預處理->編譯->彙編->鏈結。

編譯器實現編譯過程分為兩個階段:編譯和彙編;

在進行編譯之前,編譯器會有乙個編譯預處理階段

編譯預處理:

對其中的偽指令(以#開頭的指令)和特殊符號進行處理

偽指令主要包括以下五個方面:

1) 巨集定義指令,如 # define city beijing,將所有city變數都替換為beijing(字串常量city不被替換);

2.條件編譯指令,如#ifdef,#ifndef,#else,#endif ,通過定義不同的巨集來決定編譯程式對哪些**進行處理

3.#include指令,將#include<>或#include""(函式或變數,機大量外部符號宣告)的檔案按先後順序插入到原始檔中。

4.特殊符號,預編譯程式識別一些特殊的符號。如line標識解釋為當前行號,file則被解釋為當前編譯的源程式名稱。

5.預處理模組,#pragma once,#pragma warning(disable:4996)等,設定編譯器狀態或者指定編譯器完成特定動作。

編譯:編譯主要是通過詞法分析與語法分析,並對中間**進行優化(刪除公共表示式,迴圈優化,無用賦值的刪除等),在確認所有的指令都符合語法規則之後,將其翻譯成等價的中間**(組合語言**)。

經過編譯得到的輸出檔案中,只有常量,如數字,字串、變數的定義,以及c語言關鍵字

彙編:實際上是把組合語言**翻譯成目標機器指令。把這些指令打包成可重定位目標程式(relocateble object program)的格式,並把結果儲存在.o(unix中為.o,windows下是.obj)檔案中。.o檔案是二進位制目標檔案,他的位元組編碼是機器語言指令而不是ascii碼,目標檔案中所存放的也就是與源程式等效的目標的機器語言**。

下面開始分析類之間相互引用(迴圈依賴)

對乙個類(如類b)只引用另乙個類(如類c)的情況:

1.c類物件是非引用型(非指標)變數作類b的成員時,此時必須包含c的標頭檔案(標頭檔案為類c的定義),那麼程式預編譯時,將所有標頭檔案裡的內容都插入到cpp裡,此時類c的宣告定義在使用之前,可以為b類的c物件分配確定記憶體,編譯通過,如下:

2.c類物件是引用型變數(如指標),作類b的成員時,此時即可以包含c的標頭檔案,也可以只做前向宣告(最好做前向宣告,以免同一檔案被多次編譯或不被編譯,造成編譯器報重定義或者未定義錯誤),因為指標所佔記憶體是確定的,即是完整的型別。如下:

當兩個類之間存在相互引用時;

1.如果引用的是普通非指標型別變數,則會發生標頭檔案的的相互包含問題,編譯器在編譯這兩個類時,引用的型別變數的記憶體大小無法確定(編譯器要求使用前必須先定義),故無法通過編譯。(實際上兩個變數crefrenceb和bregrencec都未定義。)

2.其中乙個為指標型別,另乙個為非指標型別。

指標所指物件在堆裡開闢記憶體,非指標物件在棧裡開闢記憶體。堆記憶體開闢不能在類建構函式裡進行,因為非指標型別的變數定義未完成,會造成自身的無限巢狀,(b生a,a生b,b生a,a生b)無限死迴圈,造成記憶體溢位。

此時可以在主函式裡進行堆記憶體申請。

3.相互引用的都是指標型別時

都只能在堆裡開闢記憶體,且只能有乙個在建構函式裡構造申請堆記憶體,如果兩個建構函式同時構造這兩個物件,雖然編譯時可以確定開闢的記憶體大小,編譯通過,但建構函式會無限地為彼此申請記憶體,造成記憶體崩潰。

最好不在建構函式裡分配記憶體,而是在需要用到時在主函式內呼叫建構函式進行分配記憶體。

類的使用以及類與物件的關係

siwuxie095 1 類的定義 宣告以及使用 定義格式 宣告乙個類需要通過關鍵字 class 注意 小寫 類名遵循帕斯卡命名法 又稱 大駝峰命名法 屬性和方法可選 2 類與物件的關係 類是對某一類事物的描述,是抽象的 概念上的意義,物件是實際存在的 該類事物的每乙個個體,也被稱為例項 3 記憶體...

如何避免類的膨脹

類的膨脹 bloating 指的是類中成員過多,甚至出現無序增加的情況。過大的類,會使得複雜度急劇增加,維護會變得更為困難。所以需要控制類的增長。本文總結了一下,簡單介紹四種解決的方式,我故意用四個來講,主要為了介紹最後一種方式。以下將需要避免膨脹類稱為目標類,即類圖中的car類。這個是最為原始的思...

string類的基本使用以及常用介面

include void test 訪問容器的一種通用方式,所有支援迭代器的容器,其迭代器的使用方式完全相同 迭代器的使用方式 類似於指標的使用方式,可以通過解引用獲取元素內容,可以通過 進行位置移動 正向迭代器 void test cout endl include vector int vec ...