2010-09-27 98 views
4

我有兩個班在2個不同的文件:「缺少類型說明」 錯誤

RegMatrix.h:

#ifndef _RM_H 
#define _RM_H 
#include "SparseMatrix.h" 
... 
class RegMatrix{ 
    ... 
    RegMatrix(const SparseMatrix &s){...} //ctor 
    ... 
}; 
#endif 

SparseMatrix.h:

#ifndef _SM_H 
#define _SM_H 
#include "RegMatrix.h" 
... 
class SparseMatrix{ 
    ... 
    SparseMatrix(const RegMatrix &r){...} //ctor 
    ... 
}; 
#endif 

在構造函數行我得到的錯誤:

錯誤C4430:缺少類型說明符 - int假定。

錯誤C2143:語法錯誤:之前 '&' 失蹤 ''

但是,當我添加了類聲明

class SparseMatrix; 

在RegMatrix.h文件和

class RegMatrix; 

在SparseMatrix.h文件中它工作正常。 我的問題是爲什麼它需要,如果我有包括? 10x。

+1

標識符_RM_H和_SM_H是[保留](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier ),請勿使用它們。 – GManNickG 2010-09-27 18:15:07

回答

9

你不能有循環#include(一個文件#包含另一個#包含第一個文件)。向前聲明其中一個類而不是#include會破壞鏈並允許它工作。聲明類名允許你使用名字而不必知道類的內部位。

順便說一句,對圓形#includes的渴望是一種設計氣味。也許你可以創建一個兩個類可以依賴的接口?然後他們不必互相依賴。

+0

我有2個矩陣類。我唯一想做的就是通過獲得對SparceMatrix和相反的參考來創建一個新的RegMatrix。所以也許我根本不需要做包括? – Sanich 2010-09-27 18:15:06

+0

@Sanich,不,你可能不會。如果你想要的只是一個參考,前向聲明就足夠了。 – 2010-09-27 18:18:47

+0

在ctor im使用其他類的getter函數來獲取其私有成員,所以不包括其他類別的工作。 – Sanich 2010-09-27 18:22:28

3

如果首先包含RegMatrix.h,則將包含SparseMatrix.h。然後,這將返回到包括RegMatrix.h,並跳過,因爲頭部防護被定義。然後SparseMatrix繼續被定義,除了RegMatrix從未被宣佈。然後你得到一個錯誤。

你不能有循環包括。你必須像你一樣前向宣佈其中的一個或兩個。

5

你的頭列入將無法正常工作,看看會發生什麼,如果我解決後,包括SparseMatrix.h包括:


#ifndef _SM_H 
#define _SM_H 
/// start of #include "RegMatrix.h" 
#ifndef _RM_H 
#define _RM_H 
/// start of #include "SparseMatrix.h" inside "RegMatrix.h" 
#ifndef _SM_H 
// skipping, because _SM_H is defined and the condition is false 
#endif 
/// end of #include "SparseMatrix.h" inside "RegMatrix.h" 

class RegMatrix{ 
    ... 
    RegMatrix(const SparseMatrix &s){...} //ctor 
    ... 
}; 
#endif 


/// end of #include "RegMatrix.h" 
... 
class SparseMatrix{ 
    ... 
    SparseMatrix(const RegMatrix &r){...} //ctor 
    ... 
}; 
#endif 

所以基本上,稀疏矩陣是不確定的。你無能爲力。只需聲明你的班級前進宣言。

+1

+1以實際顯示結果。 – GManNickG 2010-09-27 18:14:10

2

之類的語句

class SparseMatrix; 

被稱爲前置聲明。它告訴編譯器「somehere」有一個這樣的名字。只要前向聲明文件使用指針或對前向引用類的引用,它就會使編譯器感到滿意並且完美工作。那是因爲,從編譯器的角度來看,指針或引用只有4個字節,與類內容無關。

在OP的代碼中,SparseMatrixRegMatrix僅用作(const)引用,所以前向聲明足以使其工作。然而,如果正向聲明文件做了某些事情需要編譯器知道它的大小,例如,

void foo(SparseMatrix); // note pass by value 

那麼編譯器會抱怨:-)

在由OP所帶來的特殊情況,我的選擇是放棄相互#include和設計正是基於前向聲明的接口。實現(即.cpp文件)可能必須包括兩個頭文件,但這不是問題。

相關問題