2013-02-15 61 views
0

我正在學習OOP並且有疑問。假設我有一個文件ClassA.h包括ClassB.h,並在某些時候我ClassB.h需要包括ClassA.hOOP C++ - A.h的錯誤包括B.h,其中又包括A.h

這yelds一個錯誤,我想我明白了,爲什麼出現這種情況,因爲我得到一個無限循環包含。但在這種情況下該怎麼辦?有沒有解決這個錯誤的方法?還是我應該重新思考我的課程以避免它?這是否意味着我的班級組織設計不佳?如果是這樣,那麼安排我的「類圖」並避免這種情況的方法是什麼?

我只是想知道什麼是在這種情況下的最佳實踐。另外,爲什麼「#pragma Once」指令不能解決這個問題?提前致謝。

+0

它應該有一個連字符分開的稱號,我會補充說,現在,遺憾的混亂。 – 2013-02-15 01:33:21

+0

通常情況下,通常會包含導致問題的實際代碼的代碼段。它可以是一個測試用例,只要它實際上存在你所問的問題,並且你已經測試了它,以確保它只是在這裏發佈。之所以這樣很難給出一個很好的具體答案。 – Omnifarious 2013-02-15 01:41:20

回答

4

有一種方法可以解決它,但這也意味着你的班級組織已經壞了。

解決它的方法被稱爲「包括警衛,雖然很多編譯器還支持#pragma once指令。我想這是行不通的,因爲#pragma once可能不考慮包含頭文件,直到整個事情被解析。由於遞歸包含發生在頭文件的中間,所以還沒有完成解析。

一個包括後衛是這樣的:

在ClassA.h:

#pragma once // Just because. It really should help. 
#ifndef INCLUDED_CLASSA_H 
#define INCLUDED_CLASSA_H 

#include "ClassB.h" 

//... rest of header file 

#endif 

在ClassB.h:

#pragma once // Just because. It really should help. 
#ifndef INCLUDED_CLASSB_H 
#define INCLUDED_CLASSB_H 

#include "ClassA.h" 

//... rest of header file 

#endif 

組織問題被稱爲循環依賴,以及循環依賴通常是一個壞主意。有很多不同的方法可以打破它們,但是要使用哪種方法取決於依賴關係的確切性質和原始原因。

根據不同的問題,你可以使用各種技術之一:

從公共基類
  • 談到這兩個類中的一個成一個基類爲其他
    • 繼承 - 這是前一個的變體。
    • 正向聲明 - 這是不希望這樣,因爲它並沒有真正打破循環依賴,它只是安排,所以你並不需要也有一個問題圓形包括依賴性。
    • 車削兩個類的某些部分成一類,它們都可以使用- 這是共同的基類的另一種變型,使用的組合物,而不是繼承的。

    還有其他技術。事實上,有一本書有各種各樣的技術可用於各種情況,因爲消除循環依賴是本書的一大主題。那本書是"Large-Scale C++ Software Design" by John Lakos

  • +1

    那麼#ifndef衛士與#pragma的工​​作方式有什麼不同?無論如何,我只是測試它,並得到同樣的問題。如果不好的做法,我會嘗試重新排列這些東西來解決這個問題。 – 2013-02-15 01:42:51

    +1

    @LeandroNogueiraCouto:那些應該工作。什麼,確切地說,你得到的錯誤是什麼?是的,這是不好的做法。 :-)它們的工作方式不同,因爲'#pragma once'由編譯器在預處理器中以供應商認爲合適的方式實現(因爲它只是一個廣泛支持的擴展)。而那些'#ifdef'後衛依靠精心指定的功能。 – Omnifarious 2013-02-15 01:43:43

    +0

    我收到了大量的錯誤,超過100個奇怪的語法錯誤和「未聲明的標識符」。 瞭解問題的名稱有很大幫助,我搜索了循環依賴關係,並發現一個簡單的前向聲明有助於我的特殊情況,以及涉及重構我的類的其他解決方案。 – 2013-02-15 02:23:56

    -1

    在我過去的經驗中,我通過使用繼承來解決了同樣的問題。

    我解決的方法是。 ClassA - > ClassB:ClassB被ClassA繼承。 ClassA具有ClassB和ClassA想要的共同需求。

    然後我下了決心「遞歸問題包括」

    +0

    #包括與繼承無關的問題 - 例如,您可能與C中的#includes具有完全相同的問題,它不支持繼承。 – 2013-02-15 02:17:36

    4

    您也可以解決這個問題,通過使用預先聲明。假如你沒有創建你在頭文件中包含的類的實際對象,或者不從它繼承,比方說,如果你只需要在頭文件中指向它們的指針,你可以這樣做。

    例子:

    ClassA.h 
    class ClassB; 
    //rest of the codes here 
    
    ClassB.h 
    class ClassA; 
    //rest of the codes here 
    
    ClassA.cpp 
    #include ClassA.h 
    #include ClassB.h 
    
    ClassB.cpp 
    #include ClassB.h 
    #inlcude ClassA.h 
    
    +0

    是的,這解決了我的問題。謝謝! – 2013-02-15 02:27:28