2012-05-08 44 views
20

Tôi là một nhà phát triển Java và tôi khá mới đối với C++. Tôi cần phải thực hiện một số loại lớp tiện ích, và tôi đã nghĩ đến việc triển khai thực hiện các phương thức tĩnh. Tuy nhiên, tôi đã xem qua this stackoverflow question về các hàm không gian tên so với phương thức tĩnh và các hàm không gian tên apprently là cách tiếp cận ưa thích. Vì vậy, tôi muốn konw nếu có bất kỳ bài viết hoặc ví dụ về cách thực hiện chức năng không gian tên. Ví dụ: làm cách nào để khai báo các hàm vùng tên trong tệp tiêu đề? Tiêu đề có nên chứa các định nghĩa hàm như tệp tiêu đề lớp và triển khai phải ở trong tệp cpp hay tôi nên thực hiện ngay các hàm trong tệp tiêu đề?Chức năng không gian tên C++

Về cơ bản, tôi đang cố gắng triển khai ứng dụng để phân tích cú pháp tệp văn bản chứa một số lệnh. Vì vậy, tôi đang nghĩ đến việc triển khai các phương thức trợ giúp tĩnh để xử lý xử lý văn bản. Ví dụ: readCommand (chuỗi dòng). Vui lòng cho tôi biết nếu tôi đi sai hướng. Cảm ơn

+1

C++ thu hút một sự phân biệt khá rõ ràng giữa chức năng và các lớp học . Nó không rõ ràng từ câu hỏi của bạn mà một trong những bạn đang quan tâm đến việc sử dụng. – Shep

+0

Hi Shep, Cảm ơn bạn đã bình luận. Tôi đã thêm nhiều chi tiết hơn cho câu hỏi của mình. Nó có trả lời câu hỏi của bạn không? –

Trả lời

19

Tôi nên khai báo hàm vùng tên trong tệp tiêu đề như thế nào?

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
// 'inline': 
inline t_ret inline_func(const t_param& pValue) { ... } 
} // << MON 

nên tiêu đề chỉ chứa các định nghĩa chức năng như file header lớp và triển khai nên trong tập tin cpp, hoặc nên tôi ngay lập tức thực hiện các chức năng trong tập tin tiêu đề?

tùy thuộc vào việc bạn có muốn chúng (có khả năng) được inlined hoặc xuất khẩu hay không. điều này thường đi xuống để giảm thiểu sự phụ thuộc.

để mở rộng xuất khẩu hoặc nội tuyến:

bạn muốn thường xuyên ủng hộ một chức năng extern để giảm thiểu sự phụ thuộc trong C++. đây là tương đương với tách nét cao từ việc kê khai trong một phương pháp học:

file.hpp

namespace MON { 
// extern: 
t_ret func(const t_param& pValue); 
} // << MON 

file.cpp

#include "hefty_stuff.hpp" 

MON::t_ret MON::func(const t_param& pValue) { ... } 
tuy nhiên

, đó là vào những thời điểm quan trọng đối với định nghĩa được hiển thị trong một số trường hợp, thường cho hiệu suất hoặc khi bạn biết kích thước là quan trọng và tiêu đề không được bao gồm nhiều nơi. do đó, biến thể inline cũng là một tùy chọn.

chức năng nội tuyến vẫn có thể được xuất và có thể được gạch dưới theo yêu cầu - tuy nhiên, bất kỳ bản sao chức năng nội tuyến nào cũng có thể được hợp nhất (cụ thể, việc triển khai là miễn phí để giả định tất cả các định nghĩa bằng nhau và bất kỳ bản sao nào của hàm không cần thiết).

với định nghĩa đã xuất, bạn có thể hạn chế chọn lọc (hoặc kiểm dịch) phụ thuộc bao gồm của bạn. nghĩa là, #include "hefty_stuff.hpp" không cần nằm trong tiêu đề để sử dụng các chức năng trong file.hpp.


Về cơ bản, tôi đang cố gắng để thực hiện một ứng dụng để phân tích một tập tin văn bản có chứa một số lệnh. Vì vậy, tôi đang nghĩ đến việc triển khai các phương thức trợ giúp tĩnh để xử lý xử lý văn bản.

well, static cần tránh ở đây. C++ sử dụng quy tắc một định nghĩa. static sẽ chỉ dẫn đến nhiều bản sao không cần thiết. Hơn nữa, một không gian tên nặc danh là C++ cách tiếp cận chức năng c của static:

namespace { 
t_ret func(const t_param& pValue) { ... } 
} // << anon 

lưu ý: không gian tên vô danh cũng có thể dẫn đến bản sao không cần thiết. lý do bạn sẽ sử dụng chúng như là một thay thế cho một hàm tĩnh là nếu bạn muốn hoặc cần phải đi chệch khỏi quy tắc một định nghĩa và không muốn khai báo biểu tượng trong phạm vi có thể được 'giải quyết'.


điểm cuối cùng liên quan đến tuyên bố template<>. với các khuôn mẫu, định nghĩa phải được hiển thị khi được sử dụng, trừ khi trình biên dịch của bạn hỗ trợ các mẫu bên ngoài. đối với mẫu, bạn có thể thực hiện hiển thị định nghĩa theo nhiều cách. thông thường, mọi người sẽ chỉ khai báo định nghĩa tại chỗ hoặc thêm tiêu đề cho các định nghĩa được bao gồm ở cuối tiêu đề hoặc khi cần. với các mẫu, hàm không cần phải được khai báo inline để tránh nhiều lỗi định nghĩa.

+0

Cảm ơn rất nhiều Justin. Bạn có thể giải thích thêm một chút về điểm "có khả năng được inlined hoặc xuất khẩu", hoặc chỉ cho tôi một số bài viết mà tôi nên đọc một bout nó? –

+2

@KHein yup - mở rộng – justin

+0

@Justin, bạn quên đề cập đến các chức năng được tạo khuôn mẫu. – Griwes

1

Tôi nên khai báo hàm vùng tên trong tệp tiêu đề như thế nào?

namespace YourNamespace 
{ 
    void fun1(); 
    void fun2(); 
} 

nên tiêu đề chỉ chứa các định nghĩa chức năng như file header lớp và triển khai nên trong tập tin cpp, hoặc nên tôi ngay lập tức thực hiện các chức năng trong tập tin tiêu đề?

Nếu chức năng của bạn trong không gian tên là tĩnh, bạn có thể triển khai các hàm trong tệp tiêu đề hoặc bạn phải triển khai trong tệp cpp.

+0

Không hoàn toàn chính xác, bạn có thể triển khai các chức năng không tĩnh trong tiêu đề. – juanchopanza

+1

@juanchopanza: Chỉ khi bạn khai báo chúng 'nội dòng'. –

+0

@Kerrek SB: đồng ý –

12

Bạn có thể khai báo các chức năng trong tiêu đề:

namespace A { 
    void foo(); 
} 

và thực hiện trong cpp:

namespace A { 
    void foo() { std::cout << "foo!"; } 
} 

Bạn cũng có thể đặt việc thực hiện trong tiêu đề, đảm bảo phải khai báo nó inline để tránh vi phạm one definition rule:

namespace A { 
    inline void foo() { std::cout << "foo()!"; } 
} 

Không e rằng việc triển khai thực hiện trong tiêu đề có nghĩa là mã máy khách có một sự phụ thuộc biên dịch vào việc triển khai thực hiện, cũng như các tiêu đề được sử dụng để thực hiện. Trong ví dụ trên, mã máy khách bây giờ phụ thuộc vào tiêu đề và nếu chúng ta làm điều gì đó tầm thường như thêm dấu chấm than vào bản in, chúng ta cần phải biên dịch lại, trái ngược với liên kết lại, tất cả mã máy khách.

Điều rất quan trọng để đưa việc triển khai các chức năng template trong tiêu đề hoặc trong một tập tin bao gồm theo tiêu đề, những không thể đi trong cpp:

namespace B { 
    template <class T> 
    inline void foo(const T& t) { std::cout << t.name() << "\n"; } 
} 
+0

+1 để triển khai thực hiện các chức năng mẫu trong tiêu đề. Định nghĩa phải được hiển thị khi được sử dụng, trừ khi trình biên dịch của bạn hỗ trợ các mẫu bên ngoài. – milesma

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