Is there a way to define circular references without using pointers?
I need to have somthing like this:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Thanks!
Is there a way to define circular references without using pointers?
I need to have somthing like this:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Thanks!
You can use references instead
struct A;
struct B {
A& a;
};
struct A {
B b;
};
But no it's not possible to create a circular reference without some level of indirection. What your sample is doing is not even creating a circular reference, it's attempting to create a recursive definition. The result would be a structure of infinite size and hence not legal.
No, there's not. Such structure would have infinite size.
You can use smart pointers (shared_ptr and weak_ptr) to avoid direct pointer manipulation, but that's about it.
How could this work? If I remember correctly, the address value of a reference can't be modified once set, so you can't define a circular reference.
It could work like the following (same as Jared's example plus constructors defined):
struct A;
struct B {
A& m_a;
B(A& a) : m_a(a) {}
};
struct A {
B m_b;
//construct B m_b member using a reference to self
A() : m_b(*this) {}
//construct B m_b member using a reference to other
A(A& other) : m_b(other) {}
};
In C++, T o
means "an object of type T
, not a reference to some T
(as, for example, with reference types in C# and Java). With the code from your question, type A
would have a sub object of type B
(named b
), and that B
in turn would have a sub object of type A
(named a
). Now, that a
would in turn have another A
inside (again called a
), which then has another B
, which...
No, this will not work.
What you probably want is that an A
referres to a B
, which in turn referres that A
. This can be done using pointers:
struct A;
struct B {
A* a;
B(A*);
};
struct A {
B* b;
A(B* b_) : b(b_) { if(b) b.a = this; }
};
B::B(A* a_) : : a(a_) { if(a) a.b = this; }
I don't think it can be done using references.
ChrisW's solution can be generalized a bit like this :
template <class defaultState> struct Context;
struct State1 {
Context<State1>& mContext;
State1(Context<State1> & ref) : mContext(ref) {}
};
template <class TDefaultState>
struct Context {
TDefaultState mState;
Context() : mState(*this) {}
};
This now allows you to do
Context<State1> demo;
Further, State can have some template helper code as well
template <class State>
struct TState {
typedef Context<State> TContext;
typedef TState<State> TBase;
Context<State> & mContext;
TState(Context<State> &ref) : mContext(ref) {}
};
struct State2 : TState<State2> {
State2(TContext & ref) : TBase(ref) {}
};
struct State3 : TState<State3> {
State3(TContext & ref) : TBase(ref) {}
};
Which now allows you to do any of
Context<State2> demo2;
Context<State3> demo3;