operador - Referencia circular en C++ sin punteros
punteros y matrices en c (5)
¿Cómo podría funcionar esto? Si recuerdo correctamente, el valor de la dirección de una referencia no se puede modificar una vez configurado, por lo que no puede definir una referencia circular.
Podría funcionar de la siguiente manera (igual que el ejemplo de Jared más constructores definidos):
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) {}
};
¿Hay alguna manera de definir referencias circulares sin usar punteros?
Necesito tener algo como esto:
struct A;
struct B {
A a;
};
struct A {
B b;
};
¡Gracias!
En C ++, T o
significa "un objeto de tipo T
, no una referencia a algunos T
(como, por ejemplo, con tipos de referencia en C # y Java). Con el código de su pregunta, el tipo A
tendría un objeto secundario de tipo B
(llamado b
), y que B
a su vez tendría un objeto secundario de tipo A
(llamado a
). Ahora, que a
tendría a su vez otra A
adentro (llamada nuevamente a
), que luego tiene otra B
, que .. .
No, esto no funcionará
Lo que probablemente quiera es que una A
refiera a una B
, que a su vez hace referencia a A
Esto se puede hacer usando punteros:
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; }
No creo que se pueda hacer usando referencias.
No, no hay. Tal estructura tendría un tamaño infinito.
Puede utilizar punteros inteligentes ( shared_ptr y weak_ptr ) para evitar la manipulación directa del puntero, pero eso es todo.
Puede usar referencias en su lugar
struct A;
struct B {
A& a;
};
struct A {
B b;
};
Pero no, no es posible crear una referencia circular sin algún nivel de indirección. Lo que su muestra está haciendo ni siquiera está creando una referencia circular, está intentando crear una definición recursiva. El resultado sería una estructura de tamaño infinito y, por lo tanto, no es legal.
La solución de ChrisW se puede generalizar de la siguiente manera:
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) {}
};
Esto ahora te permite hacer
Context<State1> demo;
Además, State también puede tener algún código auxiliar de plantilla
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) {}
};
Que ahora te permite hacer cualquiera de
Context<State2> demo2;
Context<State3> demo3;