Czy istnieje sposób definiowania odwołań cyklicznych bez użycia wskaźników?Okólnik w języku C++ bez wskaźników
muszę mieć somthing tak:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Dzięki!
Czy istnieje sposób definiowania odwołań cyklicznych bez użycia wskaźników?Okólnik w języku C++ bez wskaźników
muszę mieć somthing tak:
struct A;
struct B {
A a;
};
struct A {
B b;
};
Dzięki!
Można używać odwołań zamiast
struct A;
struct B {
A& a;
};
struct A {
B b;
};
Ale nie to nie jest możliwe, aby utworzyć odwołanie cykliczne bez pewnego poziomu zadnie. Twoja próbka nie tworzy nawet odwołania cyklicznego, ale próbuje utworzyć definicję rekursywną. Rezultatem byłaby struktura o nieskończonej wielkości, a więc nie legalna.
Jak to działa? Jeśli dobrze pamiętam, wartość adresu odniesienia nie może być zmieniana raz ustawiona, więc nie można zdefiniować odwołania kołowego. –
@John, prawdę mówiąc, nie jestem pewien. OP zadał pytanie, czy można go zdefiniować. Ta definicja jest legalna i kompiluje (VS2008 SP1). – JaredPar
Konstruktor dla B odwołałby się do A, a konstruktor dla A zainicjowałby swój element B tym *. –
Nie, nie ma. Taka struktura miałaby nieskończoną wielkość.
Możesz używać inteligentnych wskaźników (shared_ptr i weak_ptr), aby uniknąć bezpośredniego manipulowania wskaźnikami, ale to już wszystko.
Jak to działa? Jeśli dobrze pamiętam, wartość adresu odniesienia nie może być zmieniana raz ustawiona, więc nie można zdefiniować odwołania kołowego.
To może działać jak następuje (taki sam jak w przykładzie Jareda powiększonej konstruktorów zdefiniowano)
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) {}
};
Stary wątek, ale użyłem twojego rozwiązania w automatyce stanów, zobacz komentarz poniżej. – kert
W C++ T o
oznacza „oznacza przedmiot typu T
, nie powołując się na pewne T
(jak na przykład z typami referencyjnymi w języku C# i Java) Za pomocą kodu z twojego pytania typ A
miałby podrzędny obiekt typu B
(o nazwie b
), a ten z kolei miałby obiekt podrzędny typu A
(o nazwie a
) Teraz to a
ma z kolei inny A
w środku (ponownie o nazwie a
), który następnie ma inny B
, który ...
Nie, to nie zadziała.
Co prawdopodobnie chcesz, jest to, że A
referres do B
, co z kolei referres że A
. Można to zrobić za pomocą wskaźników:
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; }
Nie sądzę, że można tego dokonać za pomocą odnośników.
rozwiązanie ChrisW można uogólnić trochę tak:
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) {}
};
To teraz pozwala na wykonywanie
Context<State1> demo;
dalej, państwo może mieć jakiś szablon kodu pomocnika oraz
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) {}
};
Który teraz pozwala wykonać dowolne z
Context<State2> demo2;
Context<State3> demo3;
Uwaga: Wydaje mi się, żebym był forwardem - deklaruję "A" jako "klasę", a później definiuję ją jako "struct". – sbi
Powyższe nie może kompilować - i nie jest pod vs2008 - ponieważ A nie jest zdefiniowane, gdy definiowana jest struktura B. (btw, tak, twoje deklaracje forward: struct/class powinny pasować do definicji) – quamrana