Tạo không gian tên C ++ trong tiêu đề và nguồn (cpp)


88

Có sự khác biệt nào giữa việc gói nội dung tệp tiêu đề và tệp cpp trong một không gian tên hoặc chỉ gói nội dung tiêu đề và sau đó sử dụng không gian tên trong tệp cpp?

Sự khác biệt, ý tôi là bất kỳ hình phạt hiệu suất sắp xếp nào hoặc ngữ nghĩa hơi khác nhau có thể gây ra vấn đề hoặc bất kỳ điều gì tôi cần lưu ý.

Thí dụ:

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
namespace X
{
  void Foo::TheFunc()
  {
    return;
  }
}

VS

// header
namespace X
{
  class Foo
  {
  public:
    void TheFunc();
  };
}

// cpp
using namespace X;
{
  void Foo::TheFunc()
  {
    return;
  }
} 

Nếu không có sự khác biệt thì hình thức ưu tiên là gì và tại sao?

Câu trả lời:


37

Không gian tên chỉ là một cách để xử lý chữ ký hàm để chúng không xung đột. Một số thích cách đầu tiên và những người khác thích phiên bản thứ hai. Cả hai phiên bản không có bất kỳ ảnh hưởng nào đến hiệu suất thời gian biên dịch. Lưu ý rằng không gian tên chỉ là một thực thể thời gian biên dịch.

Vấn đề duy nhất nảy sinh với việc sử dụng không gian tên là khi chúng ta có các tên không gian tên lồng nhau giống nhau (tức là) X::X::Foo. Làm điều đó tạo ra nhiều nhầm lẫn hơn có hoặc không sử dụng từ khóa.


55

Sự khác biệt trong "không gian tên X" với "sử dụng không gian tên X" là trong phần đầu tiên, bất kỳ khai báo mới nào sẽ nằm dưới không gian tên trong khi ở khai báo thứ hai thì không.

Trong ví dụ của bạn, không có khai báo mới - vì vậy không có sự khác biệt do đó không có cách nào được ưu tiên.


Nó phụ thuộc vào dự án và phong cách. Thường thì có một không gian tên chính để tải các tệp trong một mô-đun và kiểu thứ hai có ý nghĩa.
Nicholas Wilson,

8

Không có hình phạt về hiệu suất, vì kết quả có thể giống nhau, nhưng việc đưa Foovào không gian tên của bạn sẽ ngầm tạo ra sự mơ hồ trong trường hợp bạn có Foocác không gian tên khác nhau. Bạn có thể nhận được fubar mã của bạn, thực sự. Tôi khuyên bạn nên tránh sử dụng usingcho mục đích này.

Và bạn có một lần đi lạc {sau using namespace;-)


Tôi sẽ không gọi nó là đi lạc, vì nó khớp với kết thúc }ở cuối. Tuy nhiên, tôi muốn gọi đó là cặp niềng răng dôi dư;)
blubberdiblub

@blubberdiblub, câu hỏi đã được chỉnh sửa, nếu bạn kiểm tra phiên bản gốc, bạn sẽ gọi nó là lạc ;-)
Michael Krelin - tin tặc

1

Nếu cái thứ hai cũng biên dịch, sẽ không có sự khác biệt. Không gian tên được xử lý trong thời gian biên dịch và không được ảnh hưởng đến các hành động trong thời gian chạy.

Nhưng đối với vấn đề thiết kế, thứ hai là kinh khủng. Ngay cả khi nó biên dịch (không chắc chắn), nó không có ý nghĩa gì cả.


1
Tôi không nghĩ rằng nó biên dịch, nhưng không phải vì có sự khác biệt, nhưng vì có một hoang {;-)
Michael Krelin - tin tặc

Sự khác biệt là Foo :: TheFunc () được khai báo trong namespace toàn cục, trong khi nó được định nghĩa trong không gian tên X.
bert-Jan

1

Foo :: TheFunc () không nằm trong không gian tên chính xác trong trường hợp VS. Sử dụng 'void X :: Foo :: TheFunc () {}' để triển khai hàm trong không gian tên chính xác (X).


Câu hỏi hơi cũ, nhưng bạn có biết hậu quả của việc này là gì không? tức là bạn sẽ gặp bất kỳ vấn đề nào với cách trường hợp VS của anh ấy khai báo các hàm trong không gian tên, nhưng định nghĩa chúng bên ngoài nó?
Adam Goodwin

1

Trong trường hợp nếu bạn chỉ gói nội dung .h, bạn phải viết bằng cách sử dụng không gian tên ... trong tệp cpp, nếu không, bạn mỗi lần làm việc trên không gian tên hợp lệ. Thông thường, bạn bọc cả hai tệp .cpp và .h, nếu không, bạn có nguy cơ sử dụng các đối tượng từ không gian tên khác, điều này có thể tạo ra nhiều vấn đề.


0

Tôi nghĩ điều đúng đắn cần làm ở đây là sử dụng không gian tên để xác định phạm vi.

namespace catagory
{
    enum status
    {
      none,
      active,
      paused
    }
};

void func()
{
    catagory::status status;
    status = category::active;
}

0

Nếu bạn đang cố gắng sử dụng các biến từ biến này sang biến khác, thì tôi khuyên bạn nên ngoại hóa chúng, sau đó khởi tạo chúng trong tệp nguồn như sau:

// [.hh]
namespace example
{
   extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
   int a, b, c;
}
// Then in the function below, you can init them as what you want: 
void reference
{
    example::a = 0;
}
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.