Namespace trong C++

Xét một tình huống, khi chúng ta có hai người cùng tên là Zara, trông cùng lớp. Bất cứ khi nào chúng ta cần phân biệt họ một cách trực tiếp, chúng ta phải sử dụng thông tin bổ sung cùng với tên của họ, ví dụ: vị trí họ sống và tên cha mẹ của họ, …

Tình huống tương tự xảy ra trong C++. Ví dụ: Có thể bạn đang viết một code mà có một hàm là xyz() và có thư viện khác có sẵn mà cũng có cùng hàm xyz() này. Bây giờ, compiler không biết phiên bản nào của hàm xyz() bạn muốn sử dụng trong code của bạn.

Một namespace trong C++ giúp bạn vượt qua tình huống này và được sử dụng như là thông tin bổ sung để phân biệt các hàm, lớp, biến, … cùng tên có sẵn trong các thư viện khác nhau. Sử dụng namespace trong C++, bạn có thể định nghĩa bối cảnh trong đó các tên được định nghĩa. Về bản chất, một namespace định nghĩa một phạm vi (scope) trong C++.

Định nghĩa một Namespace trong C++

Một định nghĩa namespace bắt đầu với từ khóa namespace được theo sau bởi tên của namespace đó, như sau:

namespace ten_cua_namespace {
   // phan khai bao code
}

Để gọi phiên bản namespace của hàm hoặc biến, bạn phụ thêm vào sau tên của namespace, như sau:

name::code;  // code co the la mot bien hoac mot ham.

Ví dụ sau minh họa cách namespace định nghĩa phạm vi của biến và hàm trong C++:

#include <iostream>
using namespace std;


// day la namespace dau tien
namespace dau_tien{
   void ham(){
      cout << "Ben trong namespace dau_tien" << endl;
   }
}
// day la namespace thu hai
namespace thu_hai{
   void ham(){
      cout << "Ben trong namespace thu_hai" << endl;
   }
}
int main ()
{


   // goi ham tu namespace dau tien.
   dau_tien::ham();


   // goi ham tu namespace thu hai.
   thu_hai::ham(); 


   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

using namespace directive trong C++

Bạn có thể tránh việc phụ thêm vào sau tên của namespace bằng việc sử dụng using namespace directive trong C++. Directive này nói cho compiler rằng dãy code ở sau đang sử dụng các tên được xác định trong namespace đã xác định đó. Bạn xét ví dụ:

#include <iostream>
using namespace std;


// day la namespace dau tien
namespace dau_tien{
   void ham(){
      cout << "Ben trong namespace dau_tien" << endl;
   }
}
// day la namespace thu hai
namespace thu_hai{
   void ham(){
      cout << "Ben trong namespace thu_hai" << endl;
   }
}
using namespace dau_tien;
int main ()
{


   // goi ham tu namespace dau tien.
   ham();


   return 0;
}

Biên dịch và thực thi code trên sẽ cho kết quả:

Ben trong namespace dau_tien

using namespace directive trong C++ cũng có thể được sử dụng để tham chiếu một item cụ thể trong một namespace. Ví dụ, nếu bạn chỉ có ý định sử dụng một phần cout của std namespace, bạn có thể tham chiếu nó như sau:

using std::cout;

Phần code theo sau có thể tham chiếu tới cout mà không cần phụ thêm vào sau namespace, nhưng các item khác trong std namespace vẫn cần phải rõ ràng, như sau:

#include <iostream>
using std::cout;


int main ()
{


   cout << "std::endl duoc su dung voi std!" << std::endl;


   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

std::endl duoc su dung voi std!

Các tên được giới thiệu trong một using namespace directive tuân theo các qui tắc phạm vi (scope rule). Tên là nhìn thấy bắt đầu từ vị trí của using namespace directive tới phần cuối của phạm vi mà trong đó directive này được thấy. Các thực thể với cùng tên được định nghĩa trong phạm vi bên ngoài bị ẩn.

Namespace không kề nhau trong C++

Một namespace có thể được định nghĩa thành một số phần và vì thế một namespace được tạo từ một tập hợp các phần được định nghĩa riêng biệt. Các phần riêng biệt này của một namespace có thể ở nhiều file khác nhau.

Vì thế, nếu một phần của namespace đó yêu cầu một tên được định nghĩa ở file khác, thì tên đó vẫn phải được khai báo. Định nghĩa namespace sau hoặc định nghĩa một namespace mới hoặc thêm các phần tử mới tới namespace đã tồn tại:

namespace ten_cua_namespace {
   // phan khai bao cac code
}

Namespace lồng nhau trong C++

Trong C++, namespace có thể lồng vào nhau, tức là bạn có thể định nghĩa một namespace bên trong một namespace khác, như sau:

namespace namespace_dau_tien {
   // phan khai bao cac code
   namespace namespace_thu_hai {
      // phan khai bao cac code
   }
}

Bạn có thể truy cập các thành viên của namespace lồng nhau này bởi sử dụng toán tử phân giải phạm vi (resolution operator) trong C++, như sau:

// de truy cap cac thanh vien cua namespace thu hai
using namespace namespace_dau_tien::namespace_thu_hai;


// de truy cap cac thanh vien cua namespace dau tien
using namespace namespace_dau_tien;

Trong các lệnh trên, nếu bạn đang sử dụng namespace_dau_tien, thì nó sẽ làm cho các phần tử của namespace_thu_hai có sẵn trong phạm vi đó, như sau:

#include <iostream>
using namespace std;


// day la namespace dau tien
namespace dau_tien{
   void ham(){
      cout << "Ben trong namespace dau_tien" << endl;
   }
   // day la namespace thu hai
   namespace thu_hai{
      void ham(){
         cout << "Ben trong namespace thu_hai" << endl;
      }
   }
}
using namespace dau_tien::thu_hai;
int main ()
{


   // goi ham tu namespace thu hai.
   ham();


   return 0;
}

Biên dịch và chạy chương trình C++ trên sẽ cho kết quả sau:

Ben trong namespace thu_hai

Bình luận