#include cycles disallow 'friend' function?

J

Joseph Turian

I am having difficulty defining a friend function because of a #include
cycle:

============ obj.H ================
#ifndef _obj_
#define _obj_

#include "cont.H"

class cont;

class obj {
friend void cont::foo(obj& o);
private:
void called_by_foo();
};

#endif



============ cont.H ================
#ifndef _cont_
#define _cont_

#include "obj.H"

#include <vector>

class cont {
public:
void foo(obj& o);
private:
std::vector<obj> v;
};

#endif



============ cont.C ================
#include"cont.H"


gcc -o cont.o cont.C
In file included from cont.H:4,
from cont.C:1:
obj.H:9: error: member `void cont::foo(obj&)' declared as friend before
type `cont' defined


===============

How can I fix this such that cont can contain obj, but obj can have a
member function of cont as a friend function?

Thanks,
Joseph
 
A

amparikh

Joseph said:
I am having difficulty defining a friend function because of a #include
cycle:

============ obj.H ================
#ifndef _obj_
#define _obj_

#include "cont.H"

class cont;

class obj {
friend void cont::foo(obj& o);
private:
void called_by_foo();
};

#endif



============ cont.H ================
#ifndef _cont_
#define _cont_

#include "obj.H"

#include <vector>

class cont {
public:
void foo(obj& o);
private:
std::vector<obj> v;
};

#endif



============ cont.C ================
#include"cont.H"



In file included from cont.H:4,
from cont.C:1:
obj.H:9: error: member `void cont::foo(obj&)' declared as friend before
type `cont' defined


===============

How can I fix this such that cont can contain obj, but obj can have a
member function of cont as a friend function?

Thanks,
Joseph

I think you need the forward declaration of obj in cont.h
 
V

Victor Bazarov

Joseph said:
I am having difficulty defining a friend function because of a
#include cycle:

============ obj.H ================
#ifndef _obj_
#define _obj_

#include "cont.H"

class cont;

There is no sense forward-declaring a class if you include the
file that contains its full definition. However, this does not
seem to work for you. So, drop the inclusion altogether, then.
class obj {
friend void cont::foo(obj& o);
private:
void called_by_foo();
};

#endif
[..]
obj.H:9: error: member `void cont::foo(obj&)' declared as friend
before type `cont' defined

How can I fix this such that cont can contain obj, but obj can have a
member function of cont as a friend function?

You can't. Declare the entire class 'cont' a friend of 'obj'.

V
 
A

amparikh

Victor said:
[..]
I think you need the forward declaration of obj in cont.h

Which will do what, exactly?

Unless there is another bug in VC++, but I did a quick addition of the
forward declaration and that compiled.
I think he had nested includes of header files which was causing one of
the problems...
 
P

Pete Becker

Joseph said:
I am having difficulty defining a friend function because of a #include
cycle:

Cyclic includes are never correct. Think it through: your source code
pulls in cont.h. cont.h first defines the macro _cont_, then pulls in
obj.h. obj.h first defines the macro _obj_, then pulls in cont.h. When
compiling cont.h, the compiler sees that _cont_ is already defined, so
it skips to the end of the ifndef block.

The problem has nothing to do with friend functions. You're not getting
the definition of cont at the point where you're using it in obj.h.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)
 
J

John Carson

Joseph Turian said:
I am having difficulty defining a friend function because of a
#include cycle:

============ obj.H ================
#ifndef _obj_
#define _obj_

#include "cont.H"

class cont;

class obj {
friend void cont::foo(obj& o);
private:
void called_by_foo();
};

#endif



============ cont.H ================
#ifndef _cont_
#define _cont_

#include "obj.H"

#include <vector>

class cont {
public:
void foo(obj& o);
private:
std::vector<obj> v;
};

#endif



============ cont.C ================
#include"cont.H"



In file included from cont.H:4,
from cont.C:1:
obj.H:9: error: member `void cont::foo(obj&)' declared as friend
before type `cont' defined


===============

How can I fix this such that cont can contain obj, but obj can have a
member function of cont as a friend function?

Thanks,
Joseph

If you wanted to also make a friend member declaration in cont, then you
would have a problem. However, since you only want to do it in obj, your
problem is probably soluble.

First note that you should NEVER use mutual inclusion because it it not
possible to achieve what you think you are achieving. When obj.h #includes
cont.h, that means you want cont.h read first. When cont.h #includes obj.h,
that means you want obj.h read first. Clearly, it is not possible for both
these things to be true; in any translation unit one file will be read first
and the other file will be read second. There is no way around that.

To make the member friend declaration, cont.h must be read first. Within
cont, you will need a forward declaration of obj.

By the way, you should not use leading underscores in your macro names lest
you hav a name clash with the implementation.

Your files should be:

///////////////////////////////////////////////////////////////////////
============ cont.H ================
#ifndef cont_
#define cont_


#include <vector>

class obj;

class cont {
public:
void foo(obj& o);
private:
std::vector<obj> v;
};

#endif


============ obj.H ================
#ifndef _obj_
#define _obj_

#include "cont.H"

class obj {
friend void cont::foo(obj& o);
private:
void called_by_foo();
};

#endif




============ cont.C ================
#include "obj.H"

/////////////////////////////////////////////////////////////////////////////////////

Not that the above scheme means that

std::vector<obj> v;

is being declared using an incomplete type. This is not guaranteed to
succeed, but does succeed on most implementations, including VC++ and
Comeau. If it doesn't succeed with your compiler, then you will need to
reverse the order of inclusion (read obj.h first and cont.h second) and make
the whole cont class a friend of obj, as per Victor's suggestion.
 

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
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top