2009-08-25 4 views
5

Existe-t-il un moyen de définir des références circulaires sans utiliser de pointeurs?Référence circulaire en C++ sans pointeurs

je dois avoir somthing comme ceci:

struct A; 
struct B { 
    A a; 
}; 

struct A { 
    B b; 
}; 

Merci!

+1

Remarque: Il me semble difficile d'affirmer que 'A' est un' class' et de le définir plus tard comme un 'struct'. – sbi

+0

Ce qui précède ne peut pas compiler - et n'est pas sous vs2008 - car A n'est pas défini lorsque la structure B est en cours de définition. (btw, oui vos déclarations forward: struct/class devrait correspondre aux définitions) – quamrana

Répondre

13

Vous pouvez utiliser des références à la place

struct A; 
struct B { 
    A& a; 
}; 

struct A { 
    B b; 
}; 

Mais il est impossible de créer une référence circulaire sans un certain niveau d'indirection. Ce que fait votre échantillon n'est même pas de créer une référence circulaire, il essaie de créer une définition récursive. Le résultat serait une structure de taille infinie et donc non légale.

+0

Comment cela a-t-il pu fonctionner? Si je me souviens bien, la valeur d'adresse d'une référence ne peut pas être modifiée une fois réglée, donc vous ne pouvez pas définir une référence circulaire. –

+0

@John, honnêtement, je ne suis pas sûr. L'OP a cependant demandé s'il était possible d'en définir un. Cette définition est légale et compile (VS2008 SP1). – JaredPar

+1

Le constructeur de B prendrait une référence à A, et le constructeur de A initialiserait son membre B avec * ceci. –

15

Non, il n'y en a pas. Une telle structure aurait une taille infinie.

Vous pouvez utiliser des pointeurs intelligents (shared_ptr et weak_ptr) pour éviter la manipulation directe du pointeur, mais c'est à peu près tout.

7

Comment cela a-t-il fonctionné? Si je me souviens bien, la valeur d'adresse d'une référence ne peut pas être modifiée une fois réglée, donc vous ne pouvez pas définir une référence circulaire.

Il pourrait fonctionner comme ce qui suit (comme l'exemple de Jared, plus les constructeurs définis):

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) {} 
}; 
+0

Ancien thread, mais j'ai juste utilisé votre solution dans une machine d'état, voir le commentaire ci-dessous. – kert

1

En C++, T o signifie « un objet de type T, pas une référence à certains T (comme, par exemple, avec les types de référence en C# et Java) Avec le code de votre question, tapez A aurait un sous-objet de type B (nommé b), et que B aurait à son tour un sous-objet de type A (nommé a Maintenant, ça a à son tour une autre A l'intérieur (encore une fois appelé a), qui a alors une autre B, qui ...

Non, cela ne fonctionnera pas.

Ce que vous voulez sans doute est-ce une Areferres à un B, qui à son tour referres que A. Cela peut être fait en utilisant des pointeurs:

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; } 

Je ne pense pas que cela puisse être fait en utilisant des références.

0

solution de ChrisW peut être généralisée un peu comme ceci:

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) {} 
}; 

Cela vous permet maintenant de faire

Context<State1> demo; 

En outre, l'Etat peut avoir un code d'aide de modèle ainsi

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) {} 
}; 

Qui vous permet maintenant de faire

Questions connexes