¿Hay alguna manera de definir referencias circulares sin utilizar punteros?Referencia circular en C++ sin punteros
tengo que tener algo como esto:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Gracias!
¿Hay alguna manera de definir referencias circulares sin utilizar punteros?Referencia circular en C++ sin punteros
tengo que tener algo como esto:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Gracias!
Puede usar referencias en lugar
struct A;
struct B {
A& a;
};
struct A {
B b;
};
Pero no, no es posible crear una referencia circular sin un cierto 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.
¿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. –
@John, la verdad no estoy seguro. Sin embargo, el OP preguntó si era posible definir uno. Esta definición es legal y compila (VS2008 SP1). – JaredPar
El constructor para B tomaría una referencia a A, y el constructor para A inicializaría su miembro B con * this. –
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.
¿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 como la siguiente (igual que el ejemplo de Jared más constructores definido):
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) {}
};
Tema viejo, pero acabo de usar su solución en una máquina de estado, vea el comentario a continuación. – kert
En C++, T o
significa "un objeto de tipo T
, no una referencia a algún T
(como, por ejemplo, con tipos de referencia en C# y Java). Con el código de su pregunta, escriba A
tendría un subobjeto de tipo B
(llamado b
), y que B
tendría a su vez un objeto secundario del tipo A
(llamado a
). Ahora, eso a
, a su vez tener otra A
el interior (de nuevo llama a
), que a su vez tiene otro B
, que ...
No, esto no funcionará.
Lo que probablemente quiere decir que un A
referres a un B
, que a su vez referres que 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 mediante referencias.
solución de ChrisW se puede generalizar un poco como esto:
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 le permite hacer
Context<State1> demo;
Además, Estado puede tener algo de código ayudante de plantilla, así
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 le permite hacer cualquiera de
Context<State2> demo2;
Context<State3> demo3;
Nota: me parece sospechoso reenviar-declarar 'A' para que sea una' clase' y luego definirlo como 'struct'. – sbi
Lo anterior no se puede compilar, y no en virtud de vs2008, porque A no se define cuando se está definiendo struct B. (por cierto, sí, sus declaraciones forward: struct/class deberían coincidir con las definiciones) – quamrana