c 兩個標頭檔案互相引用,如何解決?

時間 2021-05-29 23:38:27

1樓:breaker

對於這個不表達任何應用意圖的示例,直接「硬」解決:把 class B 中 A::size_type 直接改為 vector::

size_type。你可能說,這怎麼行?A::

size_type 是個 dependent typename[1](誤),可能會變化,或者是 class B 的實現者不可知的(示例 class A 寫的不標準,typedef 後少了 typename 關鍵字)。可是,都這麼規劃程式結構了,class A 和 class B 難道不是同乙個實現者?

如果在實際工程中發生這個災難,那麼便是程式設計(尤其是公共模組或庫設計)及原始檔組織的缺陷,違反了《C++ 程式設計規範》第 22、23 條[2]

[3]。雖然正確使用了第 24 條的 #ifndef _FOO_H_ #define _FOO_H_ 即內部 #include 保護符,或等價的 #pragma once,但是這些都救不了你,它們只能助力設計良好的程式結構。

基本的設計思路:

總是要在程式結構上避免出現迴圈依賴 (cyclic dependency)。從類的設計到 .cpp/.

h 檔案的組織都要遵循該原則。也就是說,類或原始檔的依賴關係圖,應該是乙個樹或者有向無環圖 (directed acyclic graph)。

在迴圈依賴難免的情況下,解決有兩種方式:

【編碼層面的技巧】使用前置宣告 (forward declaration)[4]。其它回答已述,不贅述。原理是編譯器核算指標時,它的 size 是固定值,不用看它指向的 class 的實現。

但是核算 class 及其物件的 size 時,就必需看 class 的實現了。由此還衍生出乙個慣用法——pImpl[3],作為下面設計思想的編碼實現。

【設計層面的思想】遵循物件導向設計的 SOLID[5] 原則中的「介面隔離原則」和「依賴倒置原則」。看到這種迴圈依賴程式結構,直覺就該告訴你,需要把一些東西抽象為介面——介面是一種約定形式,具體可以是函式指標(古典的指標或現代的可呼叫物)、抽象類、模板,甚至某種設計模式如迭代器、觀察者模式等。介面的目的是為了隔離變化。

以本題為例,為什麼 class A 裡要內含 class B 成員呢?究其根本是要利用 class B 的行為。那麼現在可以抽象出乙個介面 class IB,乙個抽象類,class B 是它的實現之一。

因此 class A 和 class B 現在都依賴 class IB了,迴圈依賴便消除了。

2樓:程式設計師檸檬

這裡觸發了C++的乙個知識點,叫C++前置宣告這是發生這種情況的根本原因,我在這裡大概給你講一下。

A.h:

#ifndef A_H

#define A_H

#include

"B.h"

class

A#endif

B.h:

#ifndef B_H

#define B_H

#include

"A.h"

class

B#endif

在這種迴圈依賴場景中,由於C++是按單個編譯單元編譯的,編譯報錯。

把A中的B轉成B*;

class A中先宣告B,也就是前置宣告;

A.h 移除對類B.h檔案的包含(若用了#ifdef則不必須)A.h:

#ifndef A_H

#define A_H

class B

class A

#endif

B.h:

#ifndef B_H

#define B_H

#include "A.h"

class B

#endif

因為用了前置宣告,編譯器無法確定物件的實際大小,而指標的大小在特定機器型別上是固定的(x86機器是4byte,x64機器是8byte)

c 標頭檔案包含?

San Cheung 既然是c 就簡單粗暴直接用namespace包裹吧。PS 不建議你使用這種全域性變數的組織方式,這也算是c c 的乙個大坑。 dyntkj 感覺好像在哪本書裡見過 如果沒猜錯的話看下去就有答案了。首先,標頭檔案裡一般不能定義變數。a.h ifndef A H 防止重複包含 de...

c 裡面標頭檔案,原始檔,資源檔案都是什麼?

已登出 在微控制器C程式設計中,專案一般按功能模組化進行結構化設計。將乙個專案劃分為多個功能,每個功能的相關程式放在乙個C程式文件中,稱之為乙個模組,對應的檔名即為模組名。乙個模組通常由兩個文件組成,乙個為標頭檔案 h,對模組中的資料結構和函式原型進行描述 另乙個則為C檔案 c 對資料例項或物件定義...

C 中的模板類宣告標頭檔案和實現檔案分離後,如何能實現正常編譯?

孫嘉成 把模板的宣告放在.h檔案中,實現放在.cpp檔案中,在main.cpp檔案中 include XX.cpp 同樣可以正常使用模板函式,但是這並不能實現您說的隱藏實現,只是表面上將宣告和實現分離了,沒什麼實際用處,只是看著好看一些,不建議使用。 zaoru 1.包含模型 常規寫法將實現寫在標頭...