2010-09-27 97 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文件)可能必须包括两个头文件,但这不是问题。

相关问题