简体   繁体   English

构造函数声明中的“缺少类型说明符”错误

[英]“missing type specifier” error on constructor declaration

I have 2 classes in 2 different files: 我在2个不同的文件中有2个类:

RegMatrix.h: RegMatrix.h:

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

SparseMatrix.h: SparseMatrix.h:

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

On the constructor lines I get the errors: 在构造函数行上我得到错误:

error C4430: missing type specifier - int assumed. 错误C4430:缺少类型说明符 - 假定为int。

error C2143: syntax error : missing ',' before '&' 错误C2143:语法错误:'&'之前缺少','

But when i add the classes declarations 但是当我添加类声明时

class SparseMatrix;

in the RegMatrix.h file and 在RegMatrix.h文件中

class RegMatrix;

in the SparseMatrix.h file it works fine. 在SparseMatrix.h文件中它工作正常。 My question is why is it needed if i have the includes? 我的问题是,如果我有包含,为什么需要它? 10x. 10X。

You can't have circular #includes (one file #includes another which #includes the first file). 你不能有循环#includes(一个文件#includes另一个#includes第一个文件)。 Forward declaring one of the classes instead of the #include will break the chain and allow it to work. 前面声明其中一个类而不是#include会打破链并允许它工作。 Declaring the class name allows you to use the name without having to know about the internal bits of the class. 声明类名允许您使用该名称,而无需了解该类的内部位。

BTW, the desire for circular #includes is a design smell. 顺便说一下,对圆形#includes的渴望是一种设计气味。 Perhaps you could create an interface that the two classes can depend on instead? 也许你可以创建一个两个类可以依赖的接口? Then they won't have to mutually depend on each other. 然后他们就不必相互依赖。

Your header inclusion won't work, see what would happen if i include SparseMatrix.h after resolving includes: 你的标题包含不起作用,看看如果我在解析后包括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

So basically, SparseMatrix is undefined. 所以基本上,SparseMatrix是未定义的。 You can't do anything about it. 你无能为力。 Just declare your class forward declaration. 只需申报你的班级前瞻声明。

If you include RegMatrix.h first, it will include SparseMatrix.h . 如果首先包含RegMatrix.h ,它将包含SparseMatrix.h Then that will go back to including RegMatrix.h , and skip because the header guard is defined. 然后,这将返回包括RegMatrix.h ,并跳过,因为已定义标头防护。 Then SparseMatrix continues to be defined, except RegMatrix was never even declared. 然后, SparseMatrix继续进行定义,除了RegMatrix从未甚至宣称。 Then you get an error. 然后你得到一个错误。

You cannot have circular includes. 你不能有圆形包含。 You must forward declare one or both of them, like you did. 你必须转发声明其中一个或两个,就像你做的那样。

Statements like 声明如

class SparseMatrix;

are called forward declarations. 被称为前瞻性声明。 It tells the compiler that "somehere" there is a class of that name. 它告诉编译器“某处”有一个该名称的类。 It makes the compiler happy and works perfectly as long as the forward declaring file uses either a pointer or a reference to the forward referenced class. 只要前向声明文件使用指针或对前向引用类的引用,它就会使编译器满意并且工作正常。 Thats because, from compiler point of view, pointers or references are just 4 bytes irrespective of the class contents. 这是因为,从编译器的角度来看,指针或引用只是4个字节,与类内容无关。

In OP's code, both SparseMatrix and RegMatrix are used only as (const) references, so forward declaration is sufficient to make it work. 在OP的代码中, SparseMatrixRegMatrix都只用作(const)引用,因此前向声明足以使其工作。

However, if the forward declaring file does something which requires the compiler to know its size, eg 但是,如果前向声明文件执行某些操作,需要编译器知道其大小,例如

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

then the compiler would complain :-) 然后编译器会抱怨:-)

In the particular situation posed by OP, my preference is to abandon the mutual #include altogether and design the interface just based on forward declarations. 在OP提出的特殊情况下,我倾向于完全抛弃共同的#include并仅基于前向声明来设计界面。 The implementation (ie .cpp files) may have to include both header files, but that is not a problem. 实现(即.cpp文件) 可能必须包含两个头文件,但这不是问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM