2008-09-22 37 views
7

Có cách nào để khai báo một đối tượng của một lớp trước khi lớp được tạo trong C++ không? Tôi hỏi vì tôi đang cố gắng sử dụng hai lớp, đầu tiên cần phải có một thể hiện của lớp thứ hai bên trong nó, nhưng lớp thứ hai cũng chứa một thể hiện của lớp đầu tiên. Tôi nhận ra rằng bạn có thể nghĩ rằng tôi có thể nhận được vào một vòng lặp vô hạn, nhưng tôi thực sự cần phải tạo và dụ của lớp thứ hai trước khi lớp đầu tiên.Khai báo một đối tượng ngay cả trước khi lớp đó được tạo ra

Trả lời

37

Bạn không thể làm một cái gì đó như thế này:

class A { 
    B b; 
}; 
class B { 
    A a; 
}; 

Vấn đề rõ ràng nhất là trình biên dịch không biết làm thế nào để lớn nó cần phải làm cho lớp A, vì kích thước của B phụ thuộc vào kích thước của A!

Bạn có thể, tuy nhiên, làm được điều này:

class B; // this is a "forward declaration" 
class A { 
    B *b; 
}; 
class B { 
    A a; 
}; 

Tuyên bố lớp B như một lời tuyên bố về phía trước cho phép bạn sử dụng con trỏ (và tài liệu tham khảo) đến lớp mà không chưa có định nghĩa cả lớp.

5

Bạn không thể khai báo một thể hiện của một lớp học không xác định nhưng bạn có thể khai báo một con trỏ một:

class A; // Declare that we have a class A without defining it yet. 

class B 
{ 
public: 
    A *itemA; 
}; 

class A 
{ 
public: 
    B *itemB; 
}; 
+0

... hoặc tham chiếu đến một: MyClass & rMyObject; –

0

Đây có phải là gần với những gì bạn muốn: Lớp đầu tiên chứa lớp thứ hai, nhưng lớp thứ hai (được tạo ra trước) chỉ có một tham chiếu đến lớp đầu tiên?

+0

Tôi đang thực sự cố gắng làm ngược lại, trong đó lớp đầu tiên tham chiếu đến lớp thứ hai và lớp thứ hai chứa một phiên bản của lớp đầu tiên. –

0

Đây được gọi là tham chiếu chéo. Xem here một ví dụ.

2

an elegant solution sử dụng mẫu.

template< int T > class BaseTemplate {}; 
typedef BaseTemplate<0> A; 
typedef BaseTemplate<1> B; 
// A 
template<> class BaseTemplate<0> 
{ 
public: 
    BaseTemplate() {} // A constructor 
    B getB(); 
} 

// B 
template<> class BaseTemplate<1> 
{ 
public: 
    BaseTemplate() {} // B constructor 
    A getA(); 
} 

inline B A::getB() { return A(); } 
inline A B::getA() { return B(); } 

Mã này sẽ hoạt động! Vì vậy, tại sao nó hoạt động? Lý do phải làm với cách thức biên soạn các mẫu . Mẫu trì hoãn việc tạo hàm chữ ký cho đến khi bạn thực sự sử dụng mẫu ở đâu đó. Điều này có nghĩa là không getA() và getB() sẽ có chữ ký của chúng được phân tích cho đến sau cả hai lớp A và B đã được khai báo đầy đủ . Đó là sự kỳ diệu của phương pháp này.

+0

Thú vị (mặc dù nó có nhiều lỗi chính tả). Nhưng 'getA' và 'getB' thực sự là các nhà máy: họ trả lại các phiên bản mới (theo giá trị). Một thể hiện của A không có B cũng như một cá thể B có A. – jwfearn

Các vấn đề liên quan