Skip to main content
gamedev.net
🔒 Locked

Circular Class definition

Started by zennehoy Feb 2, 2006 at 2:26 AM 8 replies 1.1k views
Original Post
zennehoy
zennehoy
Hello! I have two classes, one of which instantiates the other, and the other needs to define a function from the first as a friend:
[source lang=cpp]
class A;
class B;

class A {
    friend int B::bfunc();
};

class B {
private:
    class A a;
public:
    int bfunc();
};

Since B contains an instance of A, B must obviously be declared after A. However, this means I can't define B's bfunc as a friend of A, since at that point bfunc is unknown. Is there some way of accomplishing this without declaring all of class B as a friend? Thanks! Zen
M2tM
M2tM
edit: >null<
_____"You're using a screwdriver to nail some glue to a ming vase. " -ToohrVyk
lettel
lettel
Doesn't really make sense to me but the code below will compile.

class A;class B {private:    class A *a; // Change to a pointerpublic:    int bfunc();};class A {    friend int B::bfunc();};
Skeleton_V@T
Skeleton_V@T
Kylotan has written a good article on this, you may take a look:
The article
--> The great thing about Object Oriented code is that it can make small, simple problems look like large, complex ones <--
zennehoy
zennehoy
Quote:
Original post by lettel
Doesn't really make sense to me but the code below will compile.

*** Source Snippet Removed ***


'Tis very true, but that's cheating ;)
The question is if it's possible to resolve this circular definition without changing the basic structure of the classes. Ie, one class containing an instance to the other (NOT a pointer that is allocated in the constructor), and the other containing a similar reference (in this case a friend) that first requires the definition of the first class.

This is more of a conceptual challenge than an actual problem I have to work around: I'm just curious if there's some arcane C++ constructs that allow for this sort of circular referencing.

Zen

ps. Note that instancing one class in the other and vice versa makes no sense, since in that case a class would instance itself and its storage size be infinite. The problem here is conceptually possible, but may not be due to C++ syntax limitations.
Enigma
Enigma
The neatest way I could find was to make bfunc a non-member friend of B:
#include <iostream>class A;class B;int bfunc(B & b);class A{		friend int bfunc(B &);		int value;	public:		A()			:			value(0)		{		}		void print()		{		 	std::cout << value << '\n';		}};class B{	private:		A a;		friend int bfunc(B &);	public:		int bfunc()		{			return ::bfunc(*this);		}		void print()		{			a.print();		}};int bfunc(B & b){	b.a.value = 7;	return 0;}int main(){	B b;	b.bfunc();	b.print();}

Enigma
haegarr
haegarr
Not necessarily what you want, but
class B {public:    int bfunc();private:  class A {     friend int B::bfunc();     private:        int i;  };   class A a;};intB::bfunc() {   return a.i;}

should fulfil the mentioned needs.
ZQJ
ZQJ
If you add typedef B::A A; to haegarr's solution the syntax outside the header will be identical I think.
zennehoy
zennehoy
Quote:
Original post by haegarr
Not necessarily what you want, but
*** Source Snippet Removed ***
should fulfil the mentioned needs.


Quote:
Original post by ZQJ
If you add typedef B::A A; to haegarr's solution the syntax outside the header will be identical I think.


Interesting. You'd have to put class A in B's public space to avoid the class being private to B (ie so you can still instantiate it outside of B), but other than that I like it. Of course, you are out of luck if you add a class C similar to class B, though Enigma's solution would still work then.

Gotta say, I love these forums!
Zen
MaulingMonkey
MaulingMonkey
I'd just make B a friend of A. After all, if you can't trust the class writer/mantainer of class B to not do stupid things outside of B::bfunc(), how can you trust them to not do stupid things inside of B::bfunc()? But to each his own.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.