2010-04-01 39 views
11

Cái gì đó đã được gây phiền hà cho tôi trong một thời gian:Mỗi lớp có không gian tên riêng không?

Trí tuệ hiện nay là loại nên được giữ trong một không gian tên mà chỉ chứa các chức năng mà là một phần của giao diện phi thành viên của kiểu (xem C++ Coding tiêu chuẩn Sutter và Alexandrescu hoặc here) để ngăn chặn ADL kéo các định nghĩa không liên quan.

Điều này có nghĩa là tất cả các lớp phải có không gian tên riêng của chúng? Nếu chúng tôi giả định rằng một lớp có thể được tăng cường trong tương lai bằng cách thêm chức năng không phải là thành viên, thì không bao giờ có thể an toàn khi đặt hai loại trong không gian tên giống nhau. có thể can thiệp vào người kia.

Lý do tôi hỏi là không gian tên đang trở nên cồng kềnh đối với tôi. Tôi đang viết thư viện chỉ dành cho tiêu đề và tôi thấy mình đang sử dụng các tên lớp như dự án :: component :: class_name :: class_name. Việc triển khai của chúng được gọi là các hàm trợ giúp nhưng vì chúng không thể ở cùng một không gian tên, chúng cũng có để đủ điều kiện!

Edit:

Một số câu trả lời đã gợi ý rằng C++ namespace chỉ đơn giản là một cơ chế để tránh xung đột tên. Đây không phải là như vậy. Trong các hàm C++ có tham số được giải quyết bằng cách sử dụng Argument Dependent Lookup. Điều này có nghĩa là khi trình biên dịch cố gắng tìm định nghĩa hàm khớp với tên hàm, nó sẽ xem xét mọi hàm trong cùng một không gian tên như (các) kiểu tham số của nó khi tìm các ứng cử viên.

Điều này có thể có hậu quả không mong muốn, khó chịu như được nêu chi tiết trong A Modest Proposal: Fixing ADL. Các trạng thái cai trị của Sutter và Alexandrescu không bao giờ đặt một hàm trong cùng một không gian tên như một lớp trừ khi nó có nghĩa là một phần của giao diện của lớp đó. Tôi không thấy làm thế nào tôi có thể tuân theo quy tắc đó trừ khi tôi chuẩn bị cung cấp cho mọi lớp không gian tên riêng của mình.

Các đề xuất khác rất được hoan nghênh!

+2

"Các triển khai của chúng gọi hàm trợ giúp [phải] có đủ điều kiện" - bạn có thể đặt khai báo 'sử dụng' hoặc chỉ thị bên trong một hàm chức năng, nếu điều đó có ích. –

+4

Đối với tình yêu của tất cả mọi thứ thánh thiện, không thực thi tỷ lệ 1: 1 giữa các lớp và không gian tên. Đánh bại toàn bộ mục đích của việc có không gian tên và dẫn đến rất nhiều công việc phụ. –

+3

@ James D: Tôi không đồng ý. Tôi nghĩ rằng nó không quá đủ xa. Chúng tôi cũng cần phải đảm bảo rằng mỗi không gian tên là chính nó trong một không gian tên. –

Trả lời

7

Để tránh ADL, bạn chỉ cần hai không gian tên: một với tất cả các lớp của bạn và một với tất cả các chức năng lỏng lẻo của bạn. ADL chắc chắn không phải là một lý do chính đáng để mọi lớp có không gian tên riêng của nó.

Bây giờ, nếu bạn muốn tìm một số chức năng thông qua ADL, bạn có thể muốn tạo một không gian tên cho mục đích đó. Nhưng nó vẫn không chắc rằng bạn thực sự cần một không gian tên riêng cho mỗi lớp để tránh xung đột ADL.

0

Có thể là không. Xem Eric Lippert's post on the subject.

Couple điều ở đây:

  1. Eric Lippert là một nhà thiết kế # C, nhưng những gì anh ấy nói về thiết kế phân cấp xấu áp dụng ở đây.
  2. Rất nhiều điều đang được mô tả trong bài viết đó liên quan đến việc đặt tên cho lớp của bạn giống như một không gian tên trong C#, nhưng nhiều cạm bẫy giống nhau áp dụng cho C++.

Bạn có thể tiết kiệm một số cơn đau typedef bằng cách sử dụng typedef s nhưng đó tất nhiên chỉ là một băng trợ giúp.

+1

Lời khuyên của Eric Lippert là rất tốt cho C#, và có thể .Net nói chung, nhưng nó không thực sự áp dụng cho C++ vì các vùng tên C++ không hoạt động như nhau. Các không gian tên C++ là cần thiết trong trường hợp này để giữ cho các hàm * non-class * không rõ ràng. – Gabe

+0

Bạn vẫn không nên có tên lớp và không gian tên giống nhau. Bạn vẫn chạy vào cùng một loại vấn đề về độ phân giải. Tôi đồng ý các chức năng không phải lớp là một tidbit C# không phải giải quyết, nhưng C# có các phương thức mở rộng mà C++ không giải quyết được hoặc vì vậy tôi nghĩ rằng chúng là về ngay cả trong bộ phận đó. Trong mọi trường hợp, tôi đồng ý với bạn rằng có câu trả lời tốt hơn ở đây. Nhưng tôi không ghét mình đủ để xóa nó. –

15

No. Tôi chưa bao giờ nghe nói đến quy ước đó. Thông thường mỗi thư viện có không gian tên riêng và nếu thư viện đó có nhiều mô-đun khác nhau (ví dụ: các đơn vị lôgic khác nhau khác nhau về chức năng) thì có thể có không gian tên riêng, mặc dù một không gian tên trên mỗi thư viện là đủ.Trong thư viện hoặc không gian tên mô-đun, bạn có thể sử dụng không gian tên detail hoặc một không gian tên ẩn danh để lưu trữ chi tiết triển khai. Sử dụng một không gian tên cho mỗi lớp là, IMHO, hoàn thành quá mức cần thiết. Tôi chắc chắn sẽ né tránh điều đó. Đồng thời, tôi thực sự khuyên bạn nên có ít nhất một không gian tên cho thư viện của bạn và đặt mọi thứ trong một không gian tên đó hoặc một không gian tên phụ để tránh xung đột tên với các thư viện khác.

Để thực hiện điều này cụ thể hơn, hãy cho phép tôi sử dụng mẫu đáng tin cậy Boost C++ Libraries làm ví dụ. Tất cả các yếu tố bên trong tăng đều nằm trong boost::. Có một số mô-đun trong Boost, chẳng hạn như thư viện interprocess có không gian tên riêng như boost::interprocess::, nhưng đối với hầu hết các phần, các yếu tố tăng (đặc biệt là các yếu tố được sử dụng rất thường xuyên và trên mô-đun) chỉ đơn giản là nằm trong boost::. Nếu bạn nhìn vào bên trong, nó thường sử dụng boost::detail hoặc boost::name_of_module::detail để lưu trữ chi tiết triển khai cho không gian tên đã cho. Tôi đề nghị bạn mô hình không gian tên của bạn theo cách đó.

+0

+1 cho "không" tuy nhiên tôi sẽ không có một thư viện cho mỗi thư viện - thư viện là đơn vị triển khai. Một không gian tên thường được thực hiện với các dự án nhóm/dự án/tiểu dự án. Bạn có thể có một không gian tên mở rộng 2 libs và một exe – pm100

+1

@ pm100, vâng, nếu bạn có một dự án đa mô-đun (một với nhiều thư viện hoặc các đơn vị logic khác), thì bạn có thể hợp nhất chúng dưới một không gian tên, nhưng sau đó tôi vẫn sẽ đề xuất chia nhỏ nội bộ với một không gian tên trên mỗi thư viện. –

8

Không, không và hàng nghìn lần không! Không gian tên trong C++ không phải là yếu tố kiến ​​trúc hoặc thiết kế. Họ chỉ đơn giản là một cơ chế để ngăn chặn xung đột tên. Nếu trong thực tế bạn không có xung đột tên, bạn không cần không gian tên.

+0

Một nghìn lẻ một lần. –

+4

"Chúng chỉ đơn giản là một cơ chế để ngăn chặn xung đột tên." Sai. Không gian tên cũng để chỉ đạo ADL. Dù sao những gì họ đang "cho" là ít quan trọng hơn những gì họ thực sự * làm *, nếu những gì họ làm là không mong muốn trong một số trường hợp cụ thể. –

+2

Không gian tên chính xác * không * một cơ chế đặt tên đơn giản! Với tra cứu phụ thuộc đối số (http://en.wikipedia.org/wiki/Argument_dependent_name_lookup) mọi hàm trong cùng một không gian tên như một lớp được coi là một ứng cử viên khi một đối tượng của lớp được sử dụng. Do đó quy tắc của Sutter và Alexandrescu. – thehouse

0

Đó là một bài báo khá thú vị, nhưng sau đó cho các tác giả có cơ hội tốt. Tuy nhiên, tôi lưu ý rằng vấn đề liên quan đến chủ yếu:

  • typedef, bởi vì họ chỉ giới thiệu một bí danh và không phải là một loại mới
  • mẫu

Nếu tôi làm:

namespace foo 
{ 
    class Bar; 

    void copy(const Bar&, Bar&, std::string); 
} 

Và gọi nó:

#include <algorithms> 

#include "foo/bar.h" 

int main(int argc, char* argv[]) 
{ 
    Bar source; Bar dest; 
    std::string parameter; 
    copy(source, dest, parameter); 
} 

Sau đó, nó sẽ chọn foo::copy. Trong thực tế, nó sẽ xem xét cả hai foo::copystd::copy nhưng foo::copy không phải là mẫu sẽ được ưu tiên.

+0

Trình biên dịch sẽ vui vẻ chọn một hàm chung nếu nó phù hợp hơn so với một hàm không chung chung. Trong trường hợp của bạn, bạn không sao, nhưng không phải vì 'foo :: copy' không phải là một khuôn mẫu, nhưng vì việc cho phép' std :: copy' sẽ dẫn đến một cuộc gọi không rõ ràng. Nếu 'tham số' đã được, nói, một chuỗi chữ,' std :: copy' sẽ được chọn, bởi vì nó có thể chấp nhận một giá trị trực tiếp, trong khi 'foo :: copy' sẽ yêu cầu một chuyển đổi. –

+0

Trên thực tế, bằng cách làm cho 'tham số' một chuỗi chữ,' std :: copy' sẽ không còn được xem xét, vì vậy bạn vẫn ổn. Nhưng điểm chung là viết tắt. –

+0

Chính xác, tôi quên đề cập đến điểm về chuyển đổi. –

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