錯誤:variable 'CPerson' has initializer but incomplete type
緣由:xxx對應的類型沒有找到,只把xxx聲明瞭可是沒給出定義。編譯器無從確認你調用的構造函數是什麼,在哪兒
通常是沒有包含定義xxx的頭文件。c++
個人問題是寫出了這樣的代碼函數
class CPerson; int main(int argc, char *argv[]) { CPerson tom; // error ... } class CPerson { // Define this class };
問題在於,對前向聲明的錯誤使用this
前向聲明的定義:有些時候咱們能夠聲明一些類可是並不去定義它,固然這個類的做用也頗有限了。指針
好比class foo;code
聲明一個foo類,這個聲明,有時候也叫作前向聲明(forward declaration),在聲明完這個foo類以後,定義完這個foo類以前的時期,foo類是一個不徹底的類型(incomplete type),也就是說foo類是一個類型,可是這個類型的一些性質(好比包含哪些成員,具備哪些操做)都不知道。對象
所以這個類的做用也頗有限.編譯器
(1)不能定義foo類的對象。string
(2)能夠用於定義指向這個類型的指針或引用。(頗有價值的東西)it
(3)用於聲明(不是定義)使用該類型做爲形參或者返回類型的函數。io
正由於有前向聲明的存在,咱們在不少時候能夠簡便的作一些事情。
在c++中,若是要爲類編寫頭文件的話,通常是要#include一堆頭文件的,但利用前向聲明和c++編譯器的特性,其中大部分是不須要的。
c++編譯器作的事情主要是:1.掃描符號;2.肯定對象大小。
因此不少時候並不須要將類都include進來。
好比:
(1)因爲全部對象類型的引用所佔用的空間都是相同大的,因此c++編譯器很好確認對象大小。
class string;
class Sample
{
private:
string &s;
};
這裏只須要作一個string的前向聲明就能夠了,不須要#include <string>
(2)因爲全部類型的指針也是相同大小的。因此與(1)相似,也能夠只作前向聲明就好。
(3)聲明成員函數的形參或者是返回類型,也能夠利用前向聲明的性質。
class string;
class foo;
class Sample
{
public:
foo foo_test(foo &);
private:
string &s;
foo *f;
};
這裏,我根本沒有定義一個foo類,可是仍是能夠這樣用,由於成員函數不佔類對象的大小,因此c++編譯器仍是能夠肯定對象的大小。
前向聲明的做用在於告訴編譯器這個一個在別的地方定義的類型。這樣C++編譯器就能生成正確的符號表了。