今天一朋友問及
c++中的前置宣告問題,下面是我給出的回答。
在編寫c++
程式的時候,偶爾需要用到前置宣告
(forward declaration)
。下面的程式中,帶注釋的那行就是類
b的前置說明。這是必須的,因為類
a中用到了類
b,而類
b的宣告出現在類
a的後面。如果沒有類
b的前置說明,下面的程式將不同通過編譯,編譯器將會給出類似
「缺少型別說明符
」這樣的出錯提示。
**一:
// forwarddeclaration.h
#include
using
namespace std;
class
b; //
這是前置宣告
(forward declaration)
classa
… };
classb
; // main.cpp
#include
"forwarddeclaration.h"
intmain(int argc, char** argv)
上面程式可以順利編譯和執行
(幾乎沒有做什麼,也沒有輸出)。
是不是有了前置說明就萬事大吉了呢?我們看看下面的**
(帶陰影部分的**是新增加的):
**二:
// forwarddeclaration.h
#include
using
namespace std;
class
b; //
這是前置宣告
(forward declaration)
classa
void somemethod()
}; classb
};
// main.cpp
#include
"forwarddeclaration.h"
intmain(int argc, char** argv)
一編譯,發現**
(1)處出錯。出錯提示往往包括
(不同的編譯器給出的提示會有所不同):
1.使用了未定義的型別b;
2.「->somemethod」
的左邊必須指向類/結構
/聯合/泛型型別
原因:
1.(1)
處使用了型別
b的定義,因為呼叫了類
b中的乙個成員函式。前置宣告
class b;
僅僅宣告了有乙個
b這樣的型別,而並沒有給出相關的定義,類
b的相關定義,是在類
a後面出現的,因此出現了編譯錯誤; 2.
**一之所以能夠通過編譯,是因為其中僅僅用到
b這個型別,並沒有用到類
b的定義。
解決辦法是什麼?
將類的宣告和類的實現
(即類的定義
)分離。如下所示:
// forwarddeclaration.h
類的宣告
#include
using
namespace std;
class
b; //
這是前置宣告
(forward declaration)
classa
; classb
; // forwarddeclaration.cpp
類的實現
#include
"forwarddeclaration.h"
a::a(b* b):b(b)
void
a::somemethod()
void
b::somemethod()
// main.cpp
#include
"forwarddeclaration.h"
intmain(int argc, char** argv)
結論:前置宣告只能作為指標或引用,不能定義類的物件,自然也就不能呼叫物件中的方法了。
而且需要注意,如果將類
a的成員變數
b* b;
改寫成b& b;
的話,必須要將b在
a類的建構函式中,採用初始化列表的方式初始化,否則也會出錯。關於這點,詳見:
特殊資料型別成員變數的初始化
C 類宣告 類前置宣告
參考自 關於前置型別宣告的注意點 一 class b class a class b 上述 能夠通過編譯。二 class b class a class b 上述 報錯。error list c2079 a adata uses undefined class b c2027 use of unde...
C 模板類的前置宣告
template class linkedstack template class node template class linkedstack linkedstack bool isempty const bool isfull const t top const linkedstack add...
C 類的前置宣告用法
問題 兩個類a b相互呼叫,在兩個類a和b的標頭檔案中 include 了所需的標頭檔案,編譯報錯。為什麼呢,a需要b,b需要a,形成了迴圈,違反了程式的確定性原則。原因在於 class bbb 這種方式僅僅是一種符號宣告,告訴編譯器存在bbb這個類,不會去確定bbb這個類的所佔資源 記憶體 大小和...