下面是幾個編譯錯誤:
missing type specifier - int assumed.我想不少人會遇到上面的編譯錯誤,這很可能是交叉引用所造成的。unknown override specifier.
『ctesta』 does not name a type
雖然c++交叉引用並不是乙個很常見的問題,而且應該盡量避免交叉引用。但是如果迫不得已非要採取交叉引用的話,那有什麼好的解決方法嗎?答案是肯定的。
下面我們通過乙個簡單的例子來輔助說明。下面是某個工程下的幾個檔案:
#include "ctestb
.h"class
ctestb
virtual ~ctestb() {}
};
#include "ctesta
.h"class
ctesta
virtual ~ctesta() {}
};
#include
#include "ctesta.h"
#include "ctestb.h"
int main()
如果我們使用gnu gcc編譯器,那麼編譯結果十分的恐怖,不僅編譯時間比較長,而且產生的錯誤也會很多,你可能會得到下面的編譯日誌:
mingw32-g++.exe -wall -fexceptions -g -iinclude -c以及下面的編譯資訊:e:\blog_test\main.cpp -o obj\debug\main.o
in file included from include/ctestb.h:4:0,
from include/ctesta.h:4,
from include/ctestb.h:4,
from include/ctesta.h:4,
from include/ctestb.h:4,
from include/ctesta.h:4,
from include/ctesta.h:4,
from include/ctestb.h:4,
from include/ctesta.h:4,
from e:\blog_test\main.cpp:2:
include/ctestb.h:6:7: error: redefinition of 『class ctestb』
include\ctesta.h|4|error: #include nested too deeply我們不難發現,上面的編譯錯誤的很可能就是上述的兩個標頭檔案互相引用對方所造成的,即所謂的交叉引用。其實原理也很好理解,我們可以站在編譯器編譯器角度(think like a compiler)想一想:include\ctestb.h|4|error: #include nested too deeply
include\ctesta.h|9|error: 『ctestb』 does not name a type
include\ctestb.h|6|error: previous definition of 『class ctestb』
include\ctesta.h|6|error: redefinition of 『class ctesta』
include\ctesta.h|6|error: previous definition of 『class ctesta』
include\ctestb.h|6|error: redefinition of 『class ctestb』
include\ctestb.h|6|error: previous definition of 『class ctestb』
當你編譯編譯原始檔時,你需要為物件a
分配空間,因為a
中有成員變數m_b
(ctestb
型別),所以給a分配的空間必須足夠存放m_b
。那麼此時也必須為m_b
分配足夠存放ctesta
大小的空間…如此迴圈下去,你會發現編譯進入了乙個死鎖。於是就出現了上面我們看到的編譯結果。
note:編譯資訊取決於你使用的編譯器,使用不同的編譯器可能會得到不同的編譯結果。
為了防止編譯過程進入死鎖,我們可以在標頭檔案中加入一些特殊的巨集:
#ifndef ctestb_h
#define ctestb_h
...#endif
或者使用
#pragma once
這兩種巨集都可以確保所在檔案檔案在一次單獨編譯中只被包含一次。這兩者的優缺點比較可以在這裡找到。即使在上面的檔案中加入巨集保護,也無法完全解決問題,程式有產生了 新的編譯錯誤:
『ctesta』 does not name a type要解決上述編譯錯誤,可以採取前置宣告(forward declaration),即在定義ctesta之前,先宣告類ctestb;類ctestb同理。同時讓我們來看看標頭檔案testa.h的改變:
#ifndef ctesta_h
#define ctesta_h
#include "ctestb.h"
class ctestb;
class ctesta
virtual ~ctesta() {}
};#endif // ctesta_h
這裡我們必須要注意一點,類a中的成員變數必須是指標或引用型別。有一篇博文中很形象的講解了前置宣告,有興趣的朋友可以參考這裡。
言多必失,這裡我只用一句話作總結:在程式中我們應該盡量避免使用c++交叉引用。
resolve header include circular dependencies in c++, stackoverflow-
c++交叉引用問題,互相包含標頭檔案容易出問題,所以標頭檔案能不包含就不包含, 開源中國.
c++中前置宣告的應用與陷阱, csdn.
objective c 交叉引用問題的解決方案
objective c 不允許交叉引用,上 a.h import import b.h inte ce a nsobject void test b b 報錯點 2 end a.mm import a.h implementation a void test b b end b.h import i...
python匯入模組交叉引用
實際專案中遇到python模組相互引用問題,查資料,終於算是弄明白了。首先交叉引用或是相互引用,實際上就是匯入迴圈,關於匯入迴圈的詳細說明,可見我摘自 python核心程式設計 第二版的摘抄 python匯入迴圈方法。附錄給了一種解決交叉引用的方法,試了,不行,但關於交叉引用問題本身說明的很清楚,如...
word中的交叉引用
分別使用 交叉引用 依次插入所需應用文獻編號範圍的第乙個和最後乙個。所需引用處出現 1 3 在引用處對兩個編號操作 點選滑鼠右鍵 選擇 切換域 1 變為 3 變為 對 域進行編輯,設定引用顯示格式,分別後面加入字元 0 0 0 0 1 的域 變為 3 的域 變為 用滑鼠分別選擇修改過的 域,點選鍵盤...