views:

57

answers:

4

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.

+3  A: 

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.

GMan
+5  A: 

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.

Kristo
I have 2 matrices classes. The only thing i want to do is to create a new RegMatrix by getting a refference to a SparceMatrix and the opposite. So maybe i don't have to do includes at all?
Sanich
@Sanich, no you probably don't. The forward declaration is sufficient if all you want is a reference.
Kristo
In the ctor im using a getter functions of the other class to get its private members, so not including the other class dont work.
Sanich
@Sanich: You include it in the `.cpp`.
GMan
+4  A: 
BatchyX
+1 for actually showing the result.
GMan
+2  A: 

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, e.g.

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

ArunSaha