2011-02-08 36 views
5

Tôi đã nhìn vào SDK Fear cho dự án trường đại học của tôi, nhưng đã nhận thấy một số mã như vậy:Tại sao bao gồm tiêu đề và chuyển tiếp khai báo lớp chứa trong cùng một tệp cpp?

foo.h

class Foo 
{ 
    public: 
     int iSomething; 
}; 

Bar.cpp:

#include "Foo.h" 

// Forward declarations 
class Foo; 

Is có bất kỳ lý do cụ thể để chuyển tiếp khai báo và bao gồm các tiêu đề thích hợp trong cùng một tập tin cpp? Hoặc là tuyên bố chuyển tiếp dự phòng vì tiêu đề đang được bao gồm?

EDIT:

Mỗi lần tôi nhìn thấy nó trong mã, câu lệnh bao gồm luôn luôn trước khai báo chuyển tiếp.

Trả lời

6

Nó đơn giản là thừa, nó có khả năng có vấn đề. Nói Foo.h thay đổi để Foo trở thành một typedef cho một số instantiation cụ thể của một chung, templatised tương đương - loại điều mà có thể được dự đoán như là một phần của sự phát triển phần mềm bình thường. Sau đó Bar.cpp của "lớp X" không cần thiết sẽ gây ra một lỗi biên dịch ala:

--- fwd.h --- 
template <typename T> 
class XT 
{ 
    public: 
    int n_; 
}; 

typedef XT<int> X; 

--- fwd.cc --- 
#include "fwd.h" 

class X; 

int main() 
{ 
    X x; 
    x.n_ = 0; 
    return x.n_; 
} 

--- compilation attempt --- 
~/dev .../gcc/4.1.1/exec/bin/g++ fwd.cc -o fwd 
fwd.cc:3: error: using typedef-name 'X' after 'class' 
fwd.h:8: error: 'X' has a previous declaration here 

Đây là một lý do tôi luôn khuyên bạn sử dụng dành riêng phần đầu phía trước-khai ala <iosfwd>, duy trì với và bao gồm theo tiêu đề chính để đảm bảo liên tục Tính nhất quán. Tôi không bao giờ đặt "class X;" trong một tệp triển khai trừ khi lớp được định nghĩa trong đó. Hãy nhớ rằng những lợi ích dường như của "class X;" các khai báo chuyển tiếp không quá nhiều đến nỗi chúng tránh được một tệp #include và nhiều hơn nữa các tệp chúng bao gồm có thể lớn và bao gồm nhiều tệp khác: các tiêu đề khai báo chuyên dụng thường tránh được phần lớn số lượng đó.

1

Tuyên bố chuyển tiếp là thừa, nhưng cũng vô hại. Có lẽ tác giả sử dụng rất nhiều tờ khai chuyển tiếp và không bảo đảm nghiêm ngặt rằng chúng luôn được yêu cầu.

3

Nếu tuyên bố chuyển tiếp đến trước khi đưa vào, nó có thể loại bỏ sự phụ thuộc. Đến sau tệp .h thực sự xác định nó không làm gì cả.

+0

Bạn có thể xây dựng không? Ban đầu tôi đã viết chính xác điều này, nhưng sau đó tôi nghĩ thêm một chút về nó và thấy rằng nếu thanh chuyển tiếp tuyên bố Foo, thì ngay lập tứC#includes Foo.h, nó nên a) luôn luôn dẫn đến việc khai báo Foo, và b) không bao giờ phụ thuộc vào một tiêu đề khác đã tuyên bố Foo. Bạn có thể đưa ra ví dụ về việc có khai báo chuyển tiếp trước khi #include thực sự giúp ích không? – mgiuca

+0

@mgiuca - giảm thời gian biên dịch. đôi khi mã chỉ sử dụng con trỏ và không bao giờ yêu cầu kích thước thực của lớp [và không bao giờ tạo ra các cá thể].Trong những trường hợp đó, một khai báo chuyển tiếp đủ, giúp bạn tiết kiệm thời gian # include'ing các tệp khác. –

+0

@Foo Bah Vâng, đó là lý do chính đáng để sử dụng tờ khai chuyển tiếp * thay vì * a #include. Nhưng nó không giải thích lý do tại sao bạn có cả hai. Nếu bạn có cả hai, bạn sẽ cần xử lý tệp được bao gồm, cho dù nó đã được sử dụng hay chưa. – mgiuca

2

Bản gốc class Foo; có thể đã là dấu tích. Hãy nhớ rằng, nếu nguồn chỉ sử dụng con trỏ đến lớp Foo [và không thực sự cố gắng tạo các đối tượng Foo hoặc con trỏ Foo dereference], bạn không cần định nghĩa lớp trước khi sử dụng nó.

Nếu không nhìn thấy mã, tôi muốn gây nguy hiểm đoán rằng phiên bản gốc của bar.cpp có mã mà không cần định nghĩa của foo

tôi sử dụng tờ khai phía trước trong các dự án lớn để giảm thời gian biên dịch. thời gian biên dịch không phải là một vấn đề khi phải mất một giây, nhưng khi dự án mất một giờ để xây dựng mỗi giây sẽ giúp :)

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