Nội dung bài viết
Đăng ký học lập trình C++
Tại STDIO bạn được dạy nền tảng lập trình tốt nhất.
Đăng ký học
Tuấn Trần Namespace là một cơ chế trong C++, cho phép ta nhóm các thực thể (class, object, function…) có liên quan thành từng nhóm khác nhau theo tên, mà theo đó tên của mọi thực thể trong mỗi namespace đều được gắn thêm tên của namespace đó như tiền tố.

Giới thiệu

Chắc hẳn trước đây các bạn ít nhiều đã có sử dụng dòng mã using namespace std; khi viết các chương trình Console Application với thư viện iostream. Vậy, ý nghĩa của dòng mã đó là gì, chúng ta sẽ cùng tìm hiểu thông qua bài viết này.

Các ví dụ trong bài viết được kiểm chứng trên môi trường:

  • Visual Studio 2012
  • Windows
  • C++11

Tiền đề bài viết

Thời gian trước đây tôi hoàn toàn không sử dụng đến namespace, có lẽ do những chương trình tôi viết còn quá đơn giản. Lúc đấy trong đầu tôi nhen nhóm ý nghĩ muốn tìm hiểu ý nghĩa của tất cả những dòng mã nguồn mà tôi đã viết mà không rõ nghĩa (trong đó có using namespace std;). Hy vọng qua bài viết này, các bạn có thể hiểu rõ hơn những dòng mã nguồn mà bạn viết ra.

Đối tượng hướng đến

Bài viết dành cho những người viết mã nguồn bằng ngôn ngữ C++. Chưa biết đến hoặc mới nghe nói đến khái niệm namespace. Những lập trình viên khác có thể dùng làm tài liệu tham khảo.

Namespace là gì?

Namespace là một cơ chế trong C++, cho phép ta nhóm các thực thể (class, object, function…) có liên quan thành từng nhóm khác nhau theo tên, mà theo đó tên của mọi thực thể trong mỗi namespace đều được gắn thêm tên của namespace đó như tiền tố.

Namespace dùng để làm gì?

Trong C++, không sử dụng namespace (hay có thể hiểu là dùng chung một namespace) có thể gây ra một số rắc rối. Chẳng hạn trong ví dụ:

// lib1.h
class String
{
    // some helpful functions
};

// lib2.h
class String
{
    // some others helpful functions
};

Giả sử ta cần cả 2 lớp để xử lý một vấn đề liên quan đến chuỗi. Lúc này ta dễ dàng thấy được là không thể sử dụng cả 2 thư viện lib1.h và lib2.h cùng lúc. Do trình biên dịch sẽ báo là lớp String được khai báo lại, hoặc giả trình biên dịch không báo lỗi thì ta cũng không thể phân biệt được 2 lớp String này.

Lúc này, sử dụng namespace sẽ giải quyết được vấn đề trên:

// lib1.h
namespace lib1
{
    class String
    {
        // ...
    };
}

// lib2.h
namespace lib2
{
    class String
    {
        // some others helpful functions
    };
}

Sau khi định nghĩa như vậy, ta có thể gọi các lớp trên bằng toán tử quan hệ (::) như sau:

int main()
{
    // do something
    lib1::String a; // the String class in lib1.h
    lib2::String b; // the String class in lib2.h
    // dosomething
    return 0;
}

Không chỉ giới hạn ở 1 namespace và các class, ta cũng có thể tổ chức các namespace theo dạng cây cho các đối tượng hay hàm, như trong ví dụ sau:

namespace stdio
{
	// News
	string whatsNew; 

	namespace founders
	{
		namespace kevin
		{
			void submitTopic()
			{
				// do something
			}
		}
		// ...
	}

	namespace authors
	{
		namespace amy
		{
		}

		namespace rye
		{
			class BasicGuide
			{
				// something
			};
		}

		namespace frederick
		{
		}
	}
// ...
}

Lúc này ta có thể gọi đến chuỗi News, lớp BasicGuide, hàm submitTopic như sau: 

stdio::whatsNew;
stdio::authors::rye::BasicGuide PointerInCpp;
stdio::founders::kevin::submitTopic();

Lưu ý

Một namespace có thể chứa một hoặc nhiều thực thể hay namespace khác, nhưng một thực thể không thể chứa trong nó bất kỳ namespace nào.

Từ khóa Using

Từ khóa using có 2 cách sử dụng, và được gọi với 2 tên khác nhau:

  • Using Declaration
  • Using Directive

Using declaration

Cách gọi:

using <tên namespace>::<tên thực thể>;

Công dụng:

Khai báo này cho phép lập trình viên truy cập đến thực thể được khai báo thông qua tên namespace chứa khai báo.

Ví dụ:

Xét ví dụ tại mục 1, không chỉ có La Kiến Vinh :: www.stdio.vn/users/index/1/la-kien-vinh có nhu cầu xin đăng bài mà Rye Nguyễn :: www.stdio.vn/users/index/74/rye-nguyen, Amy Lê :: www.stdio.vn/users/index/70/amy-le hay Frederick Trần :: www.stdio.vn/users/index/95/tuan-tran cũng vậy nhưng khi gọi stdio::founders::kevin::submitTopic(); để đăng một bài của Amy Lê thì không tường minh, khi đó, ta có thể chia sẻ quyền xin đăng bài (hàm submitTopic) của Kevin La thông qua từ khóa using như sau:

namespace stdio
{
	// News
	string whatsNew;

	namespace founders
	{
		namespace kevin
		{
			void submitTopic()
			{
				// do something
			}
		}
		// ...
	}

	namespace authors
	{
		namespace amy
		{
			// be able to submit topics
			using stdio::founders::kevin::submitTopic;
		}

		namespace rye
		{
			// be able to submit topics
			using stdio::founders::kevin::submitTopic;
			class BasicGuide
			{
				// something
			};
		}

		namespace frederick
		{
			// be able to submit topics
			using stdio::founders::kevin::submitTopic;
		}
	}
// ...
}

Và như vậy ta có thể gọi hàm submitTopic như sau:

stdio::authors::amy::submitTopic();
stdio::authors::rye::submitTopic();
stdio::authors::frederick::submitTopic();

Using directive

Cách gọi:

using namespace <tên namespace>;

Công dụng:

  • using directive cho phép người viết mã nguồn gọi các thực thể trong khối namespace được khai báo mà không cần gọi tên namespace đó.
  • using directive có tác dụng kể từ dòng nó được gọi.
  • using directive có thể được gọi nhiều lần tại nhiều vị trí khác nhau trong cùng một tập tin mã nguồn, và chúng có hiệu lực song song nhau.

Ví dụ:

Xét ví dụ tại mục 2.1, ta thấy rõ ràng phải gọi rất nhiều tên namespace khi các author gọi hàm submitTopic. để rút ngắn, ta có thể viết như sau:
using namespace stdio::authors;

amy::submitTopic();
rye::submitTopic();
frederick::submitTopic();

*Kevin không nằm trong namespace authors, vậy làm sao gọi hàm submitTopic của Kevin?

using directive là một cơ chế thông minh, nó sẽ không ảnh hưởng đến các dòng mã nguồn “không cần đến nó”. Ta hoàn toàn có thể viết như sau:

using namespace stdio::authors;

amy::submitTopic();
rye::submitTopic();
frederick::submitTopic();
stdio::founders::kevin::submitTopic();

// or

using namespace stdio::authors;
using namespace stdio::founders;

amy::submitTopic();
rye::submitTopic();
frederick::submitTopic();

kevin::submitTopic();

using namespace std;

std (standard) là một gói các thực thể thường dùng được định nghĩa sẵn trong thư viện iostream thuộc các phiên bản C++ standard để tiện cho lập trình viên khi sử dụng và tránh các lỗi khai báo trùng. Một số thực thể trong std: cout, cin, string, abs, sin, cos, tan, malloc…

Lời kết

Vậy là chúng ta đã cùng nhau đi qua một nội dung nữa. Hy vọng rằng với bài viết này, tôi có thể phần nào giúp bạn hiểu hơn về dòng mã using namespace std;, hơn thế, tôi còn hy vọng bạn có thể hiểu và sử dụng namespace, using declaration, using directive thuần thục để nhờ nó, mã nguồn của bạn trông sẽ chuyên nghiệp hơn, và giải quyết được một số vấn đề về khai báo.

THẢO LUẬN
ĐÓNG