简体   繁体   中英

“missing type specifier” error on constructor declaration

I have 2 classes in 2 different files:

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

On the constructor lines I get the errors:

error C4430: missing type specifier - int assumed.

error C2143: syntax error : missing ',' before '&'

But when i add the classes declarations

class SparseMatrix;

in the RegMatrix.h file and

class RegMatrix;

in the SparseMatrix.h file it works fine. My question is why is it needed if i have the includes? 10x.

You can't have circular #includes (one file #includes another which #includes the first file). Forward declaring one of the classes instead of the #include will break the chain and allow it to work. 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. 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:


#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. You can't do anything about it. Just declare your class forward declaration.

If you include RegMatrix.h first, it will include SparseMatrix.h . Then that will go back to including RegMatrix.h , and skip because the header guard is defined. Then SparseMatrix continues to be defined, except RegMatrix was never even declared. 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.

In OP's code, both SparseMatrix and RegMatrix are used only as (const) references, so forward declaration is sufficient to make it work.

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. The implementation (ie .cpp files) may have to include both header files, but that is not a problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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