2009-08-25 39 views
5

Có cách nào để xác định tham chiếu vòng tròn mà không sử dụng con trỏ không?Tham chiếu tham chiếu trong C++ mà không có con trỏ

tôi cần phải có somthing như thế này:

struct A; 
struct B { 
    A a; 
}; 

struct A { 
    B b; 
}; 

Cảm ơn!

+1

Lưu ý: Có vẻ như cá tôi phải chuyển tiếp tuyên bố 'A' thành một' lớp' và sau đó xác định nó là một 'cấu trúc'. – sbi

+0

Ở trên không thể biên dịch - và không dưới vs2008 - bởi vì A không được định nghĩa khi cấu trúc B đang được xác định. (btw, có tờ khai chuyển tiếp của bạn: struct/class phải phù hợp với các định nghĩa) – quamrana

Trả lời

13

Bạn có thể sử dụng tài liệu tham khảo thay vì

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

struct A { 
    B b; 
}; 

Nhưng không có nó không thể tạo ra một tham chiếu vòng tròn mà không cần một mức độ nào về mình. Những gì mẫu của bạn đang làm thậm chí không tạo ra một tham chiếu vòng tròn, nó đang cố gắng tạo ra một định nghĩa đệ quy. Kết quả sẽ là một cấu trúc có kích thước vô hạn và do đó không hợp pháp.

+0

Làm thế nào có thể làm việc này? Nếu tôi nhớ chính xác, giá trị địa chỉ của tham chiếu không thể sửa đổi sau khi được đặt, do đó bạn không thể xác định tham chiếu vòng tròn. –

+0

@ John, trung thực tôi không chắc chắn. OP mặc dù được hỏi liệu có thể xác định được không. Định nghĩa này là hợp pháp và biên dịch (VS2008 SP1). – JaredPar

+1

Hàm khởi tạo cho B sẽ tham chiếu đến A và hàm tạo cho A sẽ khởi tạo thành viên B của nó bằng * this. –

15

Không, không có. Cấu trúc như vậy sẽ có kích thước vô hạn.

Bạn có thể sử dụng con trỏ thông minh (shared_ptrweak_ptr) để tránh thao tác trỏ trực tiếp, nhưng đó là về nó.

7

Cách này có thể hoạt động? Nếu tôi nhớ chính xác, giá trị địa chỉ của tham chiếu không thể sửa đổi sau khi được đặt, do đó bạn không thể xác định tham chiếu vòng tròn.

Nó có thể làm việc như sau (giống như ví dụ Jared của cộng constructors xác định):

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

Chủ đề cũ, nhưng tôi vừa sử dụng giải pháp của bạn trong máy trạng thái, xem bình luận bên dưới. – kert

1

Trong C++, T o có nghĩa là "một đối tượng kiểu T, không phải là một tham chiếu đến một số T (như, Ví dụ, với các kiểu tham chiếu trong C# và Java) Với mã số từ câu hỏi của bạn, gõ A sẽ có một đối tượng phụ thuộc loại B (tên b), và lần lượt B sẽ có một đối tượng phụ loại A (có tên a) Bây giờ, đó là a lần lượt có một số khác là A (một lần nữa gọi là a), sau đó có một số khác là B, trong đó ...

Không, điều này sẽ không hoạt động.

Những gì bạn có thể muốn là một Areferres đến một B, mà lần lượt referres rằng A. Điều này có thể được thực hiện bằng cách sử dụng con trỏ:

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

Tôi không nghĩ rằng nó có thể được thực hiện bằng cách sử dụng tài liệu tham khảo.

0

giải pháp ChrisW có thể được khái quát hóa một chút như thế này:

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

này bây giờ cho phép bạn làm

Context<State1> demo; 

Hơn nữa, Nhà nước có thể có một số mã helper mẫu cũng

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

Bây giờ, bạn có thể thực hiện bất kỳ số nào trong số

Context<State2> demo2; 
Context<State3> demo3; 
Các vấn đề liên quan