2009-01-04 33 views
20

Tôi có những nghi ngờ sau về việc sử dụng tệp tiêu đề.Các phương pháp hay nhất để sử dụng các tệp tiêu đề C++

1 - Bao gồm các lính gác đặt sau bình luận

/* Copyright Note and licence information (multiple lines) */ 
#ifndef FOO_H 
#define FOO_H 
// Header file contents 
#endif 

Herb Sutter đã giảng trong "C++ tiêu chuẩn mã hóa" đặt mã như trên là có vấn đề. Anh ta nói rằng câu lệnh "#ifndef" sẽ xuất hiện trong dòng đầu tiên của tệp tiêu đề. Tôi đã không cảm thấy điều này là thuyết phục. Điều này tiếp theo là các bạn/gals trong các tập tin tiêu đề?

2 - Sử dụng không gian tên trong các tập tin tiêu đề

#ifndef FOO_H 
#define FOO_H 
namespace FooNameSpace{ 
    // Header file contents 
} 
#endif 

Là mã trên sử dụng thực tế có đúng không? Ý tôi là, bạn có sử dụng không gian tên trong các tệp tiêu đề không? Tôi biết tại sao nhập khẩu một không gian tên trong tập tin tiêu đề là vô nghĩa nhưng những gì về một tuyên bố như trên?

Nếu phương pháp trên là phương pháp chính xác, bạn làm cách nào "khai báo chuyển tiếp" của lớp học trong một không gian tên khác? Là nó như

#ifndef FOO_H 
#define FOO_H 
namespace AnotherNameSpace{ 
    class AnotherFoo; // forward declaration 
} 

namespace FooNameSpace{ 
    // Use AnotherFoo here 
} 
#endif 

Các "về phía trước khai" là phương pháp duy nhất để tránh "cyclic phụ thuộc", có đúng không?

Trả lời

19
  1. Thứ tự của các nhân viên bảo vệ và nhận xét hoàn toàn là vấn đề về phong cách - nó sẽ không có tác động đo lường được về tốc độ biên dịch.

  2. Namespaces hoàn toàn nên được sử dụng trong các tập tin tiêu đề cho tuyên bố chức năng, các lớp học, globals, vv Những gì bạn nên không làm là sử dụng using báo cáo trong các tập tin tiêu đề - nó không thể unuse một cái gì đó trong một file nguồn trong đó bao gồm nó, và bạn không nên ép buộc includers thêm các công cụ bổ sung vào phạm vi toàn cầu. Nếu bạn cần sử dụng mọi thứ từ các không gian tên khác trong tiêu đề của mình, hãy đủ điều kiện cho mỗi tên. Đôi khi nó có thể là một nỗi đau, nhưng đó thực sự là điều đúng đắn để làm.

Ví dụ:

// WRONG! 
using namespace std; 
class MyClass 
{ 
    string stringVar; 
}; 

// RIGHT 
class MyClass 
{ 
    std::string stringVar; 
}; 

Đối với tờ khai chuyển tiếp của các tầng lớp trong không gian tên khác, bạn đã có nó hoàn toàn đúng. Chỉ cần nhớ luôn luôn đủ điều kiện AnotherFooAnotherNameSpace::AnotherFoo khi bạn tham chiếu nó bên trong tiêu đề của mình. Thật vậy, các khai báo chuyển tiếp là cách duy nhất để phá vỡ các phụ thuộc tuần hoàn.

3

Về số 1, tôi không biết bất kỳ đối số cụ thể nào về hoặc chống lại. Nhiều công ty có chính sách nơi thông báo bản quyền phải là mục đầu tiên trong tệp TRƯỚC KHI bất kỳ điều gì khác hoặc bất kỳ mã có ý nghĩa nào (có thể giả định là bạn sẽ đọc bản quyền trước khi bạn hấp thụ bất kỳ mã nào). Vì mục đích đó, #IFNDEF đã là mã. Từ quan điểm khả năng sử dụng, nó có ý nghĩa để đặt bản quyền đầu tiên bởi vì mắt bỏ qua chúng. Tuy nhiên, bất cứ điều gì mô tả các mô-đun nên đến sau #ifndef theo ý kiến ​​của tôi.

2

1) Vì nhận xét không thực sự làm bất cứ điều gì, tôi nghi ngờ nó quan trọng nhiều. Về mặt kỹ thuật, mặc dù #include bản sao và bột nhão, do đó, đưa các ý kiến ​​bên ngoài các vệ sĩ tiêu đề có thể có nghĩa là nhiều công việc cho bộ tiền xử lý.Tôi không biết liệu hầu hết các trình biên dịch có đủ thông minh để tối ưu hóa điều này (tức là nếu chúng tách nhận xét trước bước tiền xử lý) nhưng có thể bạn sẽ không nhận thấy cho đến khi bạn đạt đến hàng chục nghìn tệp tiêu đề.

2) Đúng vậy. Nếu bạn muốn đặt một lớp bên trong một không gian tên, và lớp đó sẽ được khai báo trong một tệp tiêu đề, thì sau đó nó sẽ được khai báo bên trong không gian tên, do đó phải nằm trong tệp tiêu đề. Và vâng, đó là cách bạn chuyển tiếp tuyên bố chính xác. Và có, nó là công cụ chính để tránh sự phụ thuộc cyclic (bạn cũng có thể thay đổi thiết kế của bạn, nhưng không có gì sai với cyclicness về nguyên tắc cung cấp hai lớp trong câu hỏi chỉ đề cập đến nhau bằng cách tham chiếu hoặc con trỏ và không gọi bất kỳ phương thức nào) .

7
  1. Tôi đã nghe nói rằng có ý kiến ​​ trước bao gồm bảo vệ có thể gây một số trình biên dịch bỏ lỡ một tối ưu hóa . Nếu bảo vệ là điều đầu tiên, trình biên dịch có thể nhận ra thành ngữ và thậm chí không làm phiền việc mở tiêu đề cho tiếp theo bao gồm. Trong mã số của riêng tôi, các bình luận bình thường trước bao gồm cả bảo vệ. Tôi chưa bao giờ thử nghiệm để xem liệu điều này có bất kỳ tác động nào hay không. Và tôi có khả năng sẽ không bao giờ (nhưng nếu ai đó làm, tôi sẽ quan tâm đến kết quả).

  2. Các tiêu đề khóa học phải kết hợp không gian tên - nếu không, không có gì hữu ích có thể nằm trong không gian tên . Tuy nhiên, khi bạn được đề cập, tiêu đề không được 'nhập' (cho muốn một từ tốt hơn) không gian tên vào đơn vị biên dịch với chỉ thị 'using'.

2
  1. Tôi không nghĩ thêm ý kiến ​​có bất kỳ tác động hiệu suất như chỉ bởi câu trả lời của Adam bài này.

  2. Tôi đã sử dụng bản thân không gian tên trong tệp tiêu đề, nếu bạn xác định bạn sở hữu lớp chuỗi, vì vậy nó sẽ xung đột với lớp chuỗi không gian tên std.

Sử dụng "sử dụng" từ khóa chính xác là không sai (vì nó cung cấp cho bạn rất nhiều sự tiện lợi và ít hơn rất nhiều để gõ trước khi tất cả các biến của bạn)

+5

Trong một tập tin nguồn, sử dụng "sử dụng" không phải là sai ở tất cả, nhưng trong một tập tin tiêu đề, nó là rất sai. –

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