Qt報錯: has initializer but incomplete type , 解決辦法以及前向聲明的錯誤使用

錯誤: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++編譯器就能生成正確的符號表了。

相關文章
相關標籤/搜索