Khi nào nhập tên vào không gian tên toàn cầu? (sử dụng x :: y, từ x nhập y, v.v.)


8

Tôi đã lập trình bằng nhiều ngôn ngữ trong khoảng 10 năm nay. Và tôi vẫn chưa biết khi nào nên nhập một cái gì đó vào không gian tên toàn cầu ( using x::ytrong C ++, from x import ybằng Python, v.v.), vì vậy tôi hầu như không bao giờ làm điều đó.

Nó hầu như luôn luôn là một ý tưởng tồi đối với tôi, nếu chỉ vì nó giới hạn tập hợp các tên biến tôi có thể sử dụng. Ví dụ: Nơi tôi sử dụng using namespace std;hoặc using std::string;trong C ++, tôi không thể sử dụng stringlàm tên biến nữa, điều mà tôi thỉnh thoảng làm (ví dụ: đối với các hàm tiện ích chuỗi).

Nhưng tôi tự hỏi: Có một số tình huống nhập tên vào không gian tên toàn cầu thực sự có ý nghĩa? Bất kỳ quy tắc của ngón tay cái?


Câu trả lời:


11

Trong C ++, nó thường cau mày - đặc biệt using namespace std. Không stdgian tên đó có rất nhiều tên, nhiều trong số đó là các thuật toán rất chung chung, bạn có thể nhận được một số bất ngờ cực kỳ khó chịu khi using namespace std. Một cái gì đó using std::cout;không quá tệ. Nhưng không bao giờ, bao giờ, usingbất cứ điều gì vào không gian tên toàn cầu trong một tệp tiêu đề. Đó là một vụ tấn công đội bắn.


1
Nhưng những gì về câu hỏi của tôi? Khi nào nên sử dụng x :: y hoặc nhập x từ y?
futlib

4

Bạn nên làm điều đó khi nó đơn giản hóa mã của bạn. Bạn không nên làm điều đó khi nó sẽ gây ra xung đột đặt tên hoặc khi nào sau đó có thể được đưa vào phạm vi nơi nó sẽ gây ra xung đột đặt tên, chẳng hạn như tệp tiêu đề.

Một số người nghĩ rằng nó nên hiếm. Tôi nghĩ (bên ngoài các tệp tiêu đề) không sử dụng nên rất hiếm, bởi vì tiền tố không gian tên thường không thêm bất kỳ thông tin hữu ích nào, như sử dụng tên đầy đủ của ai đó mỗi khi bạn xử lý chúng.

Hãy để tôi đặt nó theo cách này. Khi bạn xem stringnhư một tên lớp, bạn có tự động nghĩ std::stringhay mycustom::stringkhông? Nó giống như câu ngạn ngữ cũ. Khi bạn nghe thấy tiếng vó, bạn nghĩ ngựa chứ không phải ngựa vằn. Nói cách khác, using namespace stdhầu như luôn luôn không có vấn đề lớn. using namespace mycustomtương tự như vậy thường không phải là một vấn đề lớn, trừ khi nó có mâu thuẫn với std, trong trường hợp đó, không gian tên tùy chỉnh của bạn là nơi bạn muốn luôn luôn yêu cầu tiền tố.


Điều gì xảy ra nếu mycustomchứa một stringlớp. Ở đầu bạn using namespace mycustom;. Thông qua phần còn lại của mã bây giờ bạn sử dụng string. Mọi người khác đọc mã std::stringchỉ nghĩ bạn (và một vài người rất quan sát) đang suy nghĩ mycustom::string. Ở đây bạn đã đặt ngựa vằn vào bãi ngựa. Đồng thời xem stackoverflow.com/q/1452721/14065
Martin York

1
Bạn đã không đọc câu cuối cùng của tôi? Tôi đặc biệt nói nếu mycustomxung đột với stdbạn nên luôn luôn yêu cầu mycustom::tiền tố.
Karl Bielefeldt

Tôi đã làm. Vấn đề là hầu hết các không gian tên đều không lớn. Biết mọi thứ trong đó thậm chí còn khó hơn (và các phiên bản tương lai của không gian tên có thể mở rộng). Do đó, bao gồm toàn bộ không gian tên là một công thức cho thảm họa (sử dụng các mục cụ thể (trong phạm vi cụ thể nhỏ sẽ dễ kiểm soát hơn)). Nếu mã của bạn chứa doStuff(int). Và một phiên bản mới hơn mycustombổ sung doStuff(double)sau đó toàn bộ ý nghĩa của bất kỳ cuộc gọi doStuff(5.5);thay đổi nào (có khả năng mà bạn không nhận thấy).
Martin York

3

Làm việc trong Python, tôi sử dụng liên tục từ x import y (dưới dạng z), để có tên rõ ràng, súc tích để nhập tham chiếu.

Từ nhập khẩu là vô giá trong một cơ sở mã với hệ thống phân cấp không gian tên sâu. Điều này đặc biệt như vậy khi tiêu chuẩn kiểu cho codebase là PEP 8 , giới hạn độ dài dòng dưới 80 ký tự.

Ví dụ: xem xét:

import foo

foo.bar.baz.baf.perform_task(foo.bar.baz.quux.SOME_CONSTANT, foo.bar.alice.bob.preferred_hash_function, '42', foo.bar.magic_numbers.MY_SALT)

Mà thay vào đó có thể được viết:

from foo.bar import baf
from foo.bar.alice import bob
from foo.bar.baz.quux import SOME_CONSTANT
from foo.bar.magic_numbers import MY_SALT

baf.perform_task(SOME_CONSTANT, bob.preferred_hash_function, '42', MY_SALT)

Vì số nhận dạng Python phân biệt chữ hoa chữ thường và không giới hạn độ dài , chúng tôi sẽ không hết tên cho dù chúng tôi nhập bao nhiêu.

Nếu chúng tôi muốn sử dụng cùng tên trong mô-đun của mình với tư cách là một trong những mô-đun chúng tôi muốn nhập, chúng tôi có thể sử dụng bí danh cho việc nhập:

from foo.bar.alice import bob as carol

def bob(x, y):
    print "running bob function"
    return carol(x, y, 42)

0

Tùy thuộc vào lập trình viên khi sử dụng nó. IMHO tốt hơn hết là không sử dụng chúng, đặc biệt là trong các tệp tiêu đề. Nhưng có một vài trường hợp khi tôi sử dụng nó

  • Khi tôi muốn giới thiệu một cái gì đó cho một không gian tên khác, vd

    namespace cg
    {
      namespace details
      {
        //lots of stuff
        void some_cool_foo()
        {
          //uses a lot stuff from details, here because I don't want prefix everything with details::
        }
      }
      using details::some_cool_foo;
    }
  • Để bật ADL cho một số thuật toán từ không gian tên khác

    namespace n1
    {
    //some general foo
    }
    namespace n2
    {
      using n1::foo;
    //some struct
    }
    namespace n3
    {
      using n1::foo;
    //some struct
    }

Nếu tôi không muốn viết tên dài của không gian tên tại .cpp, tôi luôn có thể tạo bí danh

namespace bl = boost::lambda;
namespace fs = boost::filesystem;

xin lỗi, không thể làm nổi bật nguồn của tôi = /
kassak
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.