nested class, nested function và một ứng dụng thú vị của function object
Nguồn: http://www.gotw.ca/gotw/058.htm
Bài viết này không trình bày chi tiết về nested class trong C++ mà chỉ tập trung vào các kĩ thuật sử dụng nested class và function object để mô phỏng các nested function, một yếu tố không có trong C++. Các chi tiết về nested class có thể tìm thấy trong nhiều cuốn sách C++ khác, ví dụ cuốn Thinking in C++, tập 1.
Bài viết đưa ra ba câu hỏi và sau đó lần lượt đi tìm các câu trả lời cho chúng. Ba câu hỏi là:
1- Nested class là gì? Tại sao chúng ta cần các nested class?
2- Local class là gì? Tại sao chúng ta cần các local class?
3- Trong C++ không có khái niệm nested function. Bởi vậy, chúng ta không thể viết một đoạn mã như sau
int f( int i )
{
int j = i*2;
int g( int k )
{
return j+k;
}
j += 4;
return g( 3 );
}
Hãy đưa ra một giải pháp mô phỏng các hàm f và g sao cho đạt được một “hiệu ứng” tương tự như đoạn mã trên.
Trả lời
C++ có rất nhiều công cụ hữu ích dùng để ẩn thông tin (information hiding) và quản lí sự phụ thuộc mã nguồn (dependency management). Các đoạn mã sau đây có thể chưa hoàn toàn chính xác về mặt cú pháp, chúng được dùng để minh họa cho các kĩ thuật thiết kế mà thôi.
1- Nested class là gì? Tại sao chúng ta cần nested class?
Nested class là một class được “viết” (enclosed) bên trong phạm vi (scope) của một class khác.
// Ví dụ 1: Nested class
//
class OuterClass
{
class NestedClass
{
// ...
};
// ...
};
Trong đoạn mã trên, NestedClass là một nested class được “viết” bên trong class OuterClass. Các nested class rất hữu ích cho việc tổ chức mã nguồn, quản lí quyền truy nhập (access) và các phụ thuộc (dependencies). Các nested class tuân theo các quy tắc thông thường về quyền truy nhập giống như các dữ liệu thành phần và các hàm thành phần. Tức là, nếu NestedClass được khai báo là public thì chúng ta có thể sử dụng nó từ bất cứ đâu thông qua tên gọi OuterClass::NestedClass. Ngược lại, nếu NestedClass được khai báo là private thì chỉ có các thành phần và các hàm bạn (friends) của OuterClass là có quyền truy nhập đến nó. Thông thường, các nested class chứa các cài đặt riêng cho OuterClass, do đó thường được khai báo là private.
Chú ý rằng nested class khác với namespace. Các namespace chỉ thuần túy nhóm các tên lại với nhau chứ không mang lại khả năng quản lí quyền truy nhập. Nếu bạn muốn quản lí quyền truy nhập tới một lớp, một trong các giải pháp là viết nó thành nested class trong một class khác.
2- Local class là gì? Tại sao chúng ta cần các local class?
Local class là một class được định nghĩa bên trong một hàm thông thường hoặc một hàm thành phần (member function). Trong ví dụ sau đây, LocalClass là một local class được định nghĩa bên trong một hàm thông thường có tên là f.
// Ví dụ 2: Local class
//
int f()
{
class LocalClass
{
// ...
};
// ...
};
Giống như nested class, local class là một công cụ hữu ích phục vụ việc quản lí những sự phụ thuộc về mã nguồn (code dependencies). Trong ví dụ 2, chỉ có đoạn mã trong thân hàm f mới được phép sử dụng LocalClass. LocalClass thường chứa những cài đặt riêng cho hàm f nên không cần thiết phải có khả năng truy nhập được từ bên ngoài.
Bạn có thể sử dụng local class gần như trong mọi tình huống có thể sử dụng class thông thường. Một ngoại lệ quan trọng cần ghi nhớ là: Các local class không thể đóng vai trò tham số kiểu (template parameter). Ví dụ dưới đây trích từ tài liệu chuẩn C++:
A local type, a type with no linkage, an unnamed
type or a type compounded from any of these types
shall not be used as a template-argument for a
template type-parameter. [Example:
template
class X { /* ... */ };
void f()
{
struct S { /* ... */ };
X x3; // error: local type used as
// template-argument
X x4; // error: pointer to local type
// used as template-argument
}
-end example]
Tóm lại, cả nested class lẫn local class đều là những công cụ hữu ích của C++ dùng để ẩn thông tin và quản lí quyền truy nhập và các phụ thuộc.
Nested Funtion
Một vài ngôn ngữ (không phải C++) cho phép chúng ta viết các nested function. Giống như các nested class, nested function là một function được viết bên trong một function khác. Những đặc điểm quan trọng của nested function là:
- Các nested function có quyền truy nhập đến các biến cục bộ của hàm chứa nó.
- Các nested function là “cục bộ”, nghĩa là không thể truy nhập tới chúng từ bên ngoài, trừ khi có một con trỏ trỏ đến nested function được cung cấp bởi hàm chứa.
Nếu như các nested class hữu ích bởi chúng cho phép điều kiển sự “ẩn hiện” (visibility) của một lớp thì các nested function hữu ích bởi chúng cho phép điều khiển sự “ẩn hiện” của một hàm.
Trả lời cho câu hỏi 3: Các giải pháp sử dụng class để mô phỏng nested function trong C++
Chú ý: “mô phỏng” ở đây được hiểu theo nghĩa là: Xây dựng một class g bên trong một hàm f, sao cho f có thể sử dụng g như một nested function
void f()
{
class g { … }; g();
}
Nói đến một class được sử dụng như một function, chúng ta nghĩ ngay đến các function object. Giải pháp đầu tiên mà hầu hết mọi người sẽ đưa ra là:
2 comments