Forward Referencing Question

R

Rolf Magnus

Adam said:
Hi All,

I have this stange compiler error. I have a class B that includes
pointers to class A, therefore I have done forward referencing by doing
class A; at the start of the header file.

Ok well that works ok, but if I include the following

class B {

A* p1 ;
A* p2 ;

B(A* a1, A* a2) {p1 = a1 ; p2 = a2 ;}

bool operator==(const C2Clique& p) const { return
(a1->getId()==p.a1->getId ;)

}

Ok then I get an error messaging saying me that type A is undefined. I
have realised this is because I am using the ->getId() method of A in
the == in B.

So my question is that as A relies on B and vice versa how can I get
around this problem?

Put the implementation of the operator== into the .cpp file.
 
A

Adam Hartshorne

Hi All,

I have this stange compiler error. I have a class B that includes
pointers to class A, therefore I have done forward referencing by doing
class A; at the start of the header file.

Ok well that works ok, but if I include the following

class B {

A* p1 ;
A* p2 ;

B(A* a1, A* a2) {p1 = a1 ; p2 = a2 ;}

bool operator==(const C2Clique& p) const { return
(a1->getId()==p.a1->getId ;)

}

Ok then I get an error messaging saying me that type A is undefined. I
have realised this is because I am using the ->getId() method of A in
the == in B.

So my question is that as A relies on B and vice versa how can I get
around this problem?

Adam
 
P

Peter MacMillan

Adam said:
So my question is that as A relies on B and vice versa how can I get
around this problem?

Don't inline the method body.

eg. change

class A {
....
void f() { ... }
....
};
class B { ... };

into:

class A {
....
void f();
....
};
class B { ... };

void A::f() { ... }

Of course, what you really want to do (what I would do anyway) is define
the class in a .h include file for each class (eg. A.h and B.h) and
create an implementation for each class (eg. A.cpp and B.cpp). Then in
your B.h just include A.h before the class.


--
Peter MacMillan
e-mail/msn: (e-mail address removed)
icq: 1-874-927

GCS/IT/L d-(-)>-pu s():(-) a- C+++(++++)>$ UL>$ P++ L+ E-(-) W++(+++)>$
N o w++>$ O !M- V PS PE Y+ t++ 5 X R* tv- b++(+) DI D+(++)>$ G e++ h r--
y(--)
 
A

Adam Hartshorne

Peter said:
Don't inline the method body.

eg. change

class A {
...
void f() { ... }
...
};
class B { ... };

into:

class A {
...
void f();
...
};
class B { ... };

void A::f() { ... }

Of course, what you really want to do (what I would do anyway) is define
the class in a .h include file for each class (eg. A.h and B.h) and
create an implementation for each class (eg. A.cpp and B.cpp). Then in
your B.h just include A.h before the class.
I have done the following and stilll receive error messages

in .h file

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

class RmfSite;

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) ;
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

#endif

and in .cpp

#include "cliques.h"
#include "rmfSite.h"

C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 =
site2 ;}

bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }
 
A

Adam Hartshorne

Peter said:
Don't inline the method body.

eg. change

class A {
...
void f() { ... }
...
};
class B { ... };

into:

class A {
...
void f();
...
};
class B { ... };

void A::f() { ... }

Of course, what you really want to do (what I would do anyway) is define
the class in a .h include file for each class (eg. A.h and B.h) and
create an implementation for each class (eg. A.cpp and B.cpp). Then in
your B.h just include A.h before the class.
I should have said that I still get an RmfSite undefined error, and if I
try to move things around so that the #include in rmfSite.h is the first
called include I get an undefined in the .h file of the RmfSite Class.

Does this mean I have to put all the method in the .cpp for the RmfSite?

Adam
 
A

Adam Hartshorne

Adam said:
I have done the following and stilll receive error messages

in .h file

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

class RmfSite;

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) ;
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

#endif

and in .cpp

#include "cliques.h"
#include "rmfSite.h"

C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 =
site2 ;}

bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }

Oh further information, I set a global std::list<C2Clique*> in the .h
file of the RmfSite class. What can I do now?? I can't put that in the
..cpp file of the RmfSite!

Adam
 
M

Malte Starostik

Adam said:
I have done the following and stilll receive error messages

in .h file

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

Is this rmfSite.h or cliques.h? In the latter case, the above include
guard is wrong ;-) besides, names containing two consecutive underscores
are reserved for the implementation.
class RmfSite;

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) ;
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

#endif

and in .cpp

#include "cliques.h"
#include "rmfSite.h"

C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 =
site2 ;}

Use of initialisation lists is preferred:
C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) : s1(site1), s2(site2) {}

This one could still be defined inline, as it only assigns pointers
bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }

HTH,
Malte
 
P

Peter MacMillan

Adam said:
I have done the following and stilll receive error messages

in .h file

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

class RmfSite;

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) ;
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

why are you defining C2Clique in a file called RmfSite.h? This isn't
what I meant (read on...)
#endif

and in .cpp

#include "cliques.h"
#include "rmfSite.h"

C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 =
site2 ;}

bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }

You still havent declared rmfSite. rmfSite.h should have a decleration
of the rmfSite class but you have it above with a decleration of the
C2Clique file... or I'm missing somthing here.

observe:

//
// A.h
//
#ifndef __A_H__
#define __A_H__

class A {
//...
public:
void f();
//...
};

#endif

//
// A.cpp
//
void A::f() { /* ... */ }


//
// B.h
//
#ifndef __B_H__
#define __B_H__

#include "A.h"

class B {
A* m_a;

public:
B(A* a) { m_a = a; }
void callA();
};

#endif

//
// B.cpp
//
#include "B.h"

void B::callA() {
m_a->f();
}


--
Peter MacMillan
e-mail/msn: (e-mail address removed)
icq: 1-874-927

GCS/IT/L d-(-)>-pu s():(-) a- C+++(++++)>$ UL>$ P++ L+ E-(-) W++(+++)>$
N o w++>$ O !M- V PS PE Y+ t++ 5 X R* tv- b++(+) DI D+(++)>$ G e++ h r--
y(--)
 
A

Adam Hartshorne

Malte said:
Is this rmfSite.h or cliques.h? In the latter case, the above include
guard is wrong ;-) besides, names containing two consecutive underscores
are reserved for the implementation.




Use of initialisation lists is preferred:
C2Clique::C2Clique(RmfSite* site1, RmfSite* site2) : s1(site1), s2(site2) {}

This one could still be defined inline, as it only assigns pointers




HTH,
Malte

I still receive my undefined RmfSite error if

#include "cliques.h"
#include "rmfSite.h"

and a C2Clique is not a class or namespace name error if

#include "rmfSite.h"
#include "cliques.h"
 
A

Adam Hartshorne

Peter said:
why are you defining C2Clique in a file called RmfSite.h? This isn't
what I meant (read on...)



You still havent declared rmfSite. rmfSite.h should have a decleration
of the rmfSite class but you have it above with a decleration of the
C2Clique file... or I'm missing somthing here.

observe:

//
// A.h
//
#ifndef __A_H__
#define __A_H__

class A {
//...
public:
void f();
//...
};

#endif

//
// A.cpp
//
void A::f() { /* ... */ }


//
// B.h
//
#ifndef __B_H__
#define __B_H__

#include "A.h"

class B {
A* m_a;

public:
B(A* a) { m_a = a; }
void callA();
};

#endif

//
// B.cpp
//
#include "B.h"

void B::callA() {
m_a->f();
}
No i have declared C2Clique in cliques.h and cliques.cpp and RmfSite in
rmfsite.h and rmfSite.cpp

Adam
 
P

Peter MacMillan

Adam said:
I should have said that I still get an RmfSite undefined error, and if I
try to move things around so that the #include in rmfSite.h is the first
called include I get an undefined in the .h file of the RmfSite Class.

Does this mean I have to put all the method in the .cpp for the RmfSite?

Adam

A less code answer (I like using code examples) is that you have to
actually declare the bits of A before you start calling them. The point
of a header file (or a point, that is) is to declare the class. All
you've posted so far is a forward decleration. This is good enough for
resolving pointers and the like, but it's not enough for code (and
especially dereferencing those pointers). With only a forward
decleration available, the code only knows of the type - not the
contents of that type. So x->a() is invalid if all you've got so far is
class X (where x is presumeably an instance of X).

See the example in my other post about what goes where. hmm...


--
Peter MacMillan
e-mail/msn: (e-mail address removed)
icq: 1-874-927

GCS/IT/L d-(-)>-pu s():(-) a- C+++(++++)>$ UL>$ P++ L+ E-(-) W++(+++)>$
N o w++>$ O !M- V PS PE Y+ t++ 5 X R* tv- b++(+) DI D+(++)>$ G e++ h r--
y(--)
 
A

Adam Hartshorne

Peter said:
A less code answer (I like using code examples) is that you have to
actually declare the bits of A before you start calling them. The point
of a header file (or a point, that is) is to declare the class. All
you've posted so far is a forward decleration. This is good enough for
resolving pointers and the like, but it's not enough for code (and
especially dereferencing those pointers). With only a forward
decleration available, the code only knows of the type - not the
contents of that type. So x->a() is invalid if all you've got so far is
class X (where x is presumeably an instance of X).

See the example in my other post about what goes where. hmm...
As far as I can see this exactly what I have,


c2clique.h

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 = site2 ;}
~C2Clique() {}
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

#endif


c2clique.cpp

#include "rmfSite.h"

bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }


and in RmfSite.h I have to have a std::list<C2Cliques*>. But my error is
coming from the c2clique.cpp file with the error message

C2Clique is not a class or namespace name


Adam
 
M

Malte Starostik

Adam said:
No i have declared C2Clique in cliques.h and cliques.cpp and RmfSite in
rmfsite.h and rmfSite.cpp

Yes, but it seems you copied the include guard from RmfSite.h to
cliques.h without chaning it accordingly (see above and my other post),
so if you #include both in the same translation unit, only the first one
will make it to the compiler after preprocessing.

Cheers,
Malte
 
A

Adam Hartshorne

Adam said:
As far as I can see this exactly what I have,


c2clique.h

#ifndef __RMFSITE_H_INCLUDED__
#define __RMFSITE_H_INCLUDED__

class C2Clique {

RmfSite* s1 ;
RmfSite* s2 ;

C2Clique(RmfSite* site1, RmfSite* site2) {s1 = site1 ; s2 =
site2 ;}
~C2Clique() {}
bool C2Clique::eek:perator==(const C2Clique& p) const ;

} ;

#endif


c2clique.cpp

#include "rmfSite.h"

bool C2Clique::eek:perator==(const C2Clique& p) const { return
(s1->getId()==p.s1->getId() && s2->getId()==p.s2->getId()) ||
(s1->getId()==p.s2->getId() && s2->getId()==p.s1->getId()); }


and in RmfSite.h I have to have a std::list<C2Cliques*>. But my error is
coming from the c2clique.cpp file with the error message

C2Clique is not a class or namespace name


Adam
Also if I add into c2clique.cpp

#include "c2clique.h" before the include of the rmfSite I get the
following message

syntax error : missing ';' before '*'

Adam
 
A

Adam Hartshorne

Malte said:
Yes, but it seems you copied the include guard from RmfSite.h to
cliques.h without chaning it accordingly (see above and my other post),
so if you #include both in the same translation unit, only the first one
will make it to the compiler after preprocessing.

Cheers,
Malte
Thank you guys for all the help. I have Spotted the include guard
problem. I bet you can't guess who is working at 3.30am :) and making
trivial mistakes

Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,202
Messages
2,571,057
Members
47,662
Latest member
sxarexu

Latest Threads

Top