2011-07-22 30 views
5

thể trùng lặp:
Proper way to #include when there is a circular dependency?Mutual bao gồm trong C++ .. nó hoạt động như thế nào?

Tôi khá mới để C++ và có câu hỏi yêu cầu trong tiêu đề. Hoặc chính xác hơn: Nếu A.h bao gồm B.h và B.h bao gồm A.h, tôi nhận được thông báo lỗi vì "include # file" C: ... \ A.h "bao gồm chính nó". Tập tin: B.h

Tôi không thể tìm ra cách để giải quyết vấn đề này, và thiết lập chung của tôi khá nhiều đòi hỏi mối quan hệ giữa các lớp đó. Bất kỳ khả năng nào để thực hiện công việc này?

+0

Câu hỏi hay. Preprocessor làm việc theo từng dòng, bạn sẽ nghiên cứu cách '# ifdef',' # define' và '# endif' làm việc :-) – Stan

Trả lời

6

Đơn giản: đừng để A.h bao gồm B.h. Và ngược lại.

Nói chung, tệp tiêu đề nên bao gồm ít nhất có thể. Bạn có thể sử dụng tờ khai chuyển tiếp để nhận được rất nhiều bao gồm. Thời gian duy nhất bạn hoàn toàn phải bao gồm một cái gì đó trong một tiêu đề là nếu có các đối tượng được sử dụng như không tham chiếu trong tiêu đề đó.

Vì vậy, hãy tránh thực hiện điều đó. Sử dụng Pimpl để tránh đưa các thành viên lớp vào tiêu đề. Và trừ khi đó là mã mẫu hoặc bạn cần hỗ trợ nội tuyến, không viết mã thực trong tiêu đề.

Trường hợp xấu nhất là bạn sẽ cần phải tạo một C.h xác định những gì A.h và B.h cần.

+1

TIL: Chuyển tiếp delcaration =) – ArniBoy

+0

Cảm ơn @Nicol, đó là một điểm tốt. Nói chung (không phải trong trường hợp cụ thể của việc bao gồm hai lần), bạn có thể vui lòng giải thích tại sao bạn muốn một tờ khai chuyển tiếp đến một sự bao gồm bình thường? – Enzo

7

Sử dụng Bao gồm bảo vệ trong tệp tiêu đề của bạn. http://en.wikipedia.org/wiki/Include_guard

#ifndef MYHEADER_H 
#define MYHEADER_H 

//add decls here 

#endif 

Bằng cách này nếu các tập tin tiêu đề của bạn có nhiều hơn một lần trình biên dịch bỏ qua chúng.

Cũng như quy tắc chung nếu bạn bao gồm B.h có A.h, tốt hơn nên bao gồm A.h và B.h trong ứng dụng của bạn thay vì dựa vào sự bao gồm của B.h.

Cũng chỉ đặt các khai báo trong tệp tiêu đề.

Tránh định nghĩa ở tất cả các chi phí trong tệp tiêu đề.

0

Hãy thử thêm lính gác header,

#ifndef _A_H_ 
#define _A_H_ 
... 
.. 
. 
#endif /* #ifndef _A_H_ */ 

Bạn không bao giờ nên bao gồm một tập tin header hai lần, kết quả trong định nghĩa lại ..

0

Khi một tập tin tiêu đề được thêm vào một tập tin nó được bao gồm trong phần tiền xử lý biên dịch. Vì vậy, kể cả B.h vào A.h. Và bao gồm A.h trong B.h. Đó là loại đệ quy vô hạn và tệp được bao gồm nhiều lần.

Bao gồm B.h trong A.h số tiền A.h < - B.h Bao gồm A.h trong B.h số tiền Bh < - A.h

Vì vậy, vua của vòng lặp vô hạn.

1

Bạn không nói những phụ thuộc lẫn nhau là gì, vì vậy đây chỉ là những dự đoán. Trong tất cả những điều này, tôi giả định rằng A.h định nghĩa class A và B.h được xác định class B.

Trường hợp 1: Phụ thuộc lẫn nhau là thông qua con trỏ hoặc tham chiếu.
Ví dụ: class A chứa thành viên dữ liệu thuộc loại B* và ngược lại. Trong trường hợp này, tiêu đề không cần phải là #include. Thay vào đó, hãy sử dụng một tuyên bố chuyển tiếp.

Trường hợp 2: Phụ thuộc lẫn nhau là thông qua các đối tượng.
Ví dụ: class A chứa thành viên dữ liệu thuộc loại B và ngược lại. Trong trường hợp này, bạn được hosed.

Trường hợp 3: Phụ thuộc hỗn hợp.
Ví dụ: class A chứa thành viên dữ liệu thuộc loại B nhưng class B chứa thành viên dữ liệu thuộc loại A*. Bây giờ A.h cần phải #include B.h, nhưng B.h chỉ cần một tuyên bố về phía trước của class A.

Bạn nên luôn sử dụng một số loại bảo vệ một lần để ngăn tiêu đề được bao gồm nhiều lần.

1

Giả sử rằng trong mỗi tiêu đề bạn có một lớp học, bạn có thể làm như thế này:

header file: "Ah"

#ifndef A_H 
#define A_H 
Class B; 

Class A { 
public: 
    B name_of_B_; 
} 

#endif 

Với #ifndef A_H #define A_H #endif bạn đảm bảo rằng mỗi tiêu đề được bao gồm chỉ một lần . Bạn nên sử dụng điều này trong hầu hết mọi tập tin tiêu đề mà bạn tạo ra, không chỉ trong trường hợp đặc biệt của việc đưa vào kép này. Với Class B; bạn tuyên bố rằng ở đâu đó một lớp có tên "B" sẽ được xác định.

Class B { 
public: 
    A name_of_A_; 
} 

#endif 

Câu chuyện giống với lớp "B". Bằng cách này bạn tránh sự bao gồm vòng lặp vô hạn.

+1

Bao gồm hiện tại ở cuối mỗi tệp tiêu đề hoàn toàn vô dụng. Tuyên bố chuyển tiếp như Class A; là một cơ chế để báo cho trình biên dịch rằng lớp A sẽ có mặt sau, tương tự cho lớp B. Tại thời điểm này, nó không quan trọng khi một trong hai lớp A hoặc B sẽ được giải quyết, bởi vì bạn vừa nói với trình biên dịch rằng chúng cả hai sẽ ở đó vào cuối quá trình biên dịch bằng cách sử dụng tờ khai chuyển tiếp. Vì vậy, bao gồm ở phần cuối của tập tin tiêu đề có thể được gỡ bỏ vì chúng không phục vụ mục đích nào. Trân trọng;) – ForceMagic

+0

Phải! Cảm ơn đã chỉ ra điều đó. – Enzo

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