Vietnamese Developers’ Blog

Gọi repaint() nhiều lần trong JFrame và JApplet

Posted in Java by kiennguyen on November 22, 2008

Khi học Java, chúng ta thường bắt gặp những chương trình đơn giản về animation trong các sách dạy AWT và Swing, chẳng hạn như chương trình sau đây:

import java.awt.*;
import javax.swing.*;

public class Animation1 {

  public static void main( String[] args ) {

     Animation1 gui = new Animation1();
     gui.go();

  }

  private void go() {

     JFrame frame = new JFrame();
     frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );

     panel_ = new MyPanel();
     frame.getContentPane().add( panel_, BorderLayout.CENTER );

     frame.setSize( 500, 500 );
     frame.setVisible( true );

     for( int i = 0; i < 400; i++ ) {

        x_++;
        y_++;

        panel_.repaint();

        try {
          Thread.sleep( 10 );
        } catch( Exception ex ) { }

     }

  }

  class MyPanel extends JPanel {

     public void paintComponent( Graphics g ) {

         g.setColor( Color.white );
         g.fillRect( 0, 0, this.getWidth(), this.getHeight() );

         g.setColor( Color.green );
         g.fillOval( x_, y_, 40, 40 );

     }

  }

  private JPanel panel_;
  private int x_ = 0;
  private int y_ = 0;

}

Chương trình này vẽ ra một vòng tròn trên một panel, tính toán lại tọa độ của nó rồi gọi repaint() để vẽ lại vòng tròn. Phương thức repaint() yêu cầu các component trên frame tự vẽ lại.Thao tác vẽ lại liên tục với các vị trí khác nhau sẽ tạo ra cảm giác vòng tròn chạy trên panel. Câu lệnh Thread.sleep(10) làm giảm tốc độ di chuyển của vòng tròn giúp người dùng dễ theo dõi.

Chúng ta thử sáng tạo thêm một chút bằng cách thêm vào frame một button dùng kể kích hoạt animation (học event handler và inner class luôn). Animation sẽ được kích hoạt khi người dùng ấn nút “Start animation”. Chương trình được cải tiến như sau: (more…)

Tagged with: ,

vim plugin for NetBeans

Posted in Java by kiennguyen on November 20, 2008

Khi đã quen viết code trên vi/vim rồi thì chuyển sang editor khác thật khó chịu. Phiền hà nhất là các thao tác di chuyển con trỏ (phải dùng các phím mũi tên lên xuống rất mất thời gian), xóa một từ hoặc một dòng (phải giữ Backspace mỏi cả tay), nhảy giữa các từ…Tóm lại với những ai đã quen lập trình trên vi/vim thì việc phải chuyển sang các IDE khác sẽ không khác gì cực hình.

Giải pháp cho vấn đề này là cài đặt vim plugin cho IDE đang sử dụng. Một IDE đang được sử dụng rộng rãi là NetBeans. Để cài đặt vim plugin cho NetBeans, vào link dưới đây để tải về file cài đặt:

http://sourceforge.net/projects/viex/

Giải nén để nhận được file start-module-myvim.nbm. Từ menu của NetBeans, chọn Tools->Plugins->Downloaded->Add Plugins rồi chọn file start-module-myvim.nbm. Chúng ta sẽ thấy biểu tượng của vim nằm bên cạnh các icon khác như trong hình dưới đây. (Chú ý hình dáng của con trỏ, chúng ta đang ở chế độ lệnh của vim).

Bây giờ thì chúng ta đã có thể tận hưởng sự tiện lợi trong việc viết code bằng vim kết hợp với những tính năng phức tạp cung cấp bởi NetBeans. Tuy nhiên, plugin này vẫn chưa hỗ trợ một số thao tác edit trong vim như

- Không tự động indent khi xuống dòng bằng phím o.

- Không hỗ trợ shift-o

- Không hỗ trợ ctrl-r (redo).

- Không hỗ trợ xoá nhiều từ liền nhau (d 2 w, d 3 w, d $,…)

Tuy nhiên với những tính năng hiện có của plugin này thì công việc lập trình trên NetBeans đã trở nên thú vị hơn rất nhiều. Hi vọng những khiếm khuyết nói trên sẽ được khắc phục trong những phiên bản sau.

Tagged with: ,

Linked List (1) – Basic

Posted in C/C++ by Hoang Tran on July 26, 2008

Lấy từ tài liệu tuyệt vời này về linked list của trường Stanford mà tôi muốn khái lược lại bằng những đoạn mã trong đó. Danh sách liên kết (linked list) là một kiến thức rất cơ bản của cấu trúc dữ liệu và giải thuật. Hiểu được những ưu và khuyết điểm của nó sẽ giúp chúng ta hiểu các vấn đề về thời gian, không gian bộ nhớ và cấu trúc dữ liệu nói chung. Hơn thế nữa học về linked list là một cách rất tốt để hiểu về pointer. Những bài toán về linked list là sự kết hợp rất “đẹp” giữa giải thuật (algorithms) và các phép toán với con trỏ (pointer manipulation). Linked list là cách các lập trình viên luyện tập để thực sự hiểu về pointer và bạn sẽ thấy ngôn ngữ C “đẹp” vô cùng :-) Hãy tham khảo thêm tài liệu của Stanford để hiểu kỹ thêm (Highly recommend!)


(more…)

StringTokenizer

Posted in C/C++ by Hoang Tran on July 21, 2008

StringTokenizer là một class thường được viết trong các dự án. Đó là một class dùng để xử lý chuỗi, chia tách chuỗi thành các chuỗi con (token) được phân cách bởi các ký tự định nghĩa trước (delimiter). Ví dụ:

“Hoang Tran:1982:Hanoi University of Technology” được phân cách bởi ký tự “:” để thu được thông tin tương ứng về tên, năm sinh và trường học.

Có rất nhiều cách thể hiện lớp StringTokenizer này ở các ngôn ngữ khác nhau (Java thì đã có trong JDK của nó rồi) Bạn có thể google để tìm tham khảo các cách viết đó. Dựa trên ý tưởng của java, chúng ta sẽ xây dựng một lớp StringTokenizer hữu dụng trong C++.

Trong nhiều cách viết lớp này ở trên mạng thì mình cũng nhận ra rằng cách viết ở dự án cũ là tối ưu, hay và dễ hiểu nhất :-) Sử dụng deque làm storage data cho lớp StringTokenizer sẽ làm cho quá trình insert cũng như delete các beginning và end của container rất nhanh.

Đây là lớp StringTokenizer đã được thêm bớt chút ít sau khi đi chôm :-D

(more…)

[Basic] Pointer

Posted in C/C++ by Hoang Tran on April 2, 2008

Phần này sẽ khái lược rất nhanh một vài điểm về các quy tắc sử dụng con trỏ. Để tham khảo toàn diện về con trỏ và bộ nhớ hãy xem tài liệu Pointers and Memory http://cslibrary.stanford.edu/102/).

- Pointer/Pointee: Một con trỏ “pointer” sẽ lưu một reference đến một biến khác được biết như là pointee của nó. Con trỏ có thể được thiết lập giá trị NULL có nghĩa là nó refer đến một pointee nào. (Trong C và C++, giá trị NULL có thể được sử dụng như là giá trị boolean false).

- Dereference: Toán tử dereference trên con trỏ cho phép truy nhập vào pointee của nó. Một pointer chỉ có thể bị dereference sau khi nó được thiết lập trỏ đến một pointee cụ thể. Một pointer mà không có pointee thì là bad pointer và không thể bị dereference.

- Bad pointer: Một pointer mà không được trỏ vào một pointee thì là “bad” và không thể dereference. Trong C và C++, việc dereference một bad pointer đôi khi gây xung đột ngay lập tức và làm hỏng bộ nhớ của chương trình đang chạy, gây nên “không biết đường nào mà lần”. Kiểu lỗi này rất khó để theo dõi. Trong C và C++, tất cả các pointer bắt đầu bằng bad values (những giá trị ngẫu nhiên), do đó rất dễ tình cờ sử dụng bad pointer. Những đoạn mã đúng sẽ thiết lập mỗi pointer có một good value trước khi sử dụng chúng. Chính vì vậy sử dụng bad pointer là một lỗi rất phổ biến trong C/C++. Với Java và các ngôn ngữ khác, các pointers được tự động bắt đầu với giá trị NULL, do đó quá trình dereference sẽ được dễ dàng detect nên các chương trình Java dễ gỡ lỗi này hơn nhiều.

- Pointer assignment: Một phép gán giữa hai con trỏ như p = q; sẽ làm cho hai pointer trỏ vào cùng một pointee. Nó sẽ không copy vùng nhớ của pointee. Sau phép gán thì cả hai pointer sẽ chỉ vào cùng một vùng nhớ của pointee.

- malloc(): malloc() là một hàm hệ thống mà cấp pháp một vùng nhớ trong “heap” và trả về con trỏ tới vùng nhớ mới đó. Prototype của malloc() và các hàm khác ở trong stdlib.h. Tham số của malloc() là một số nguyên là kích thước của vùng nhớ cần cấp phát tính theo bytes. Không giống như các biến cục bộ (“stack”), vùng nhớ heap không tự động giải phóng khi hàm tạo thoát ra. malloc() sẽ trả về NULL nếu nó không thế đáp ứng được yêu cầu cấp phát. Bạn nên kiểm tra trường hợp NULL với assert() nếu bạn mong nó an toàn. Hầu hết các hệ điều hành tiên tiến sẽ ném ra một exception hoặc làm việc bắt lỗi tự động trong việc cấp phát bộ nhớ của chúng, do đó không nhất thiết là trong đoạn mã của bạn phải kiểm tra việc cấp phát bộ nhớ thất bại.

- free(): free() thì ngược với malloc(). Gọi hàm free() trên vùng nhớ trên heap để chỉ ra rằng hệ thống đã thực hiện xong và giải phóng vùng nhớ đó. Tham số của free là một con trỏ tới vùng nhớ trên heap – con trỏ mà chúng ta đã có được thông qua lời gọi tới hàm malloc().

Tagged with:

Các kiểu khởi tạo biến

Posted in C/C++ by kiennguyen on February 23, 2008

Một bài viết nhỏ để warm-up cái blog sau những ngày đông giá lạnh :-D

Nguồn: http://www.gotw.ca/gotw/001.htm

Câu hỏi: Cho biết sự khác nhau của những dòng khởi tạo biến sau đây

SomeType t;
SomeType t();
SomeType t( u );
SomeType t = u;

Trả lời:

SomeType t;

Biến t được khởi tạo bởi default constructor SomeType::SomeType()

SomeType t();

Một dòng lệnh dễ gây nhầm lẫn! Thực ra đây là dòng khai báo một HÀM không có tham số và trả về một giá trị kiểu SomeType.

SomeType t( u );

Đây là dòng lệnh khởi tạo biến trực tiếp (direct initialization). Biến t được khởi tạo nhờ constructor SomeType::SomeType( u );

SomeType t = u;

Nhiều người nhầm lẫn rằng lệnh này gọi đến toán tử gán (assignment operator). Thực ra đây là một khởi tạo sao chép, trong đó t được khởi tạo nhờ copy constructor của lớp SomeType. Nếu u không thuộc kiểu SomeType thì constructor SomeType::SomeType( u ) sẽ được gọi để tạo ra một đối tượng tạm thời kiểu SomeType từ u, sau đó đối tượng này sẽ được sao chép sang t bởi copy constructor.

(more…)

Tagged with: ,

Unix programming with standard I/O (2)

Posted in C/C++, Unix/Linux/BSD by kiennguyen on January 22, 2008

Phần 2: Chương trình hiển thị nội dung file theo từng trang màn hình

1. Đặt vấn đề

Khi xem nội dung một file dài, chúng ta thường muốn nội dung file đó được hiển thị lần lượt theo từng trang màn hình. Hai lệnh phổ biến để xem nội dung file là cat và more không đáp ứng được nhu cầu này (chúng không có khả năng này, hoặc có nhưng không tiện dụng, “tác giả” cũng không biết rõ về tất cả các khả năng của hai lệnh này). Bởi vậy, chúng ta sẽ phát triển một chương trình tên là p làm nhiệm vụ in ra nội dung một file theo từng trang màn hình (screenful-at-a-time). Chương trình sẽ đợi người dùng ấn một phím để chuyển sang hiển thị trang tiếp theo. Giống như vis, p nhận dữ liệu vào từ cả file lẫn standard input. Ví dụ:

p nhận dữ liệu vào từ file

$ p vis.c

p nhận dữ liệu vào từ standard input

$ grep  ‘#define’  *.[ch]  |  p

Ở phiên bản đầu tiên, p sẽ hiển thị nội dung file theo từng khối, mỗi khối 22 dòng (phần lớn các terminal gồm 24 dòng văn bản). Một cách đơn giản để nhắc người dùng ấn một phím để tiếp tục là không in ra kí tự new line nằm cuối dòng thứ 22. Khi đó, con trỏ sẽ nằm ở cuối dòng thứ 22 thay vì đầu dòng thứ 23. Khi người dùng ấn phím enter, kí tự new line còn thiếu của dòng 22 sẽ được thêm vào, nhờ đó dòng tiếp theo (dòng 23) sẽ được in ra ở đúng vị trí của nó. Nếu người dùng ấn ctrl-d hay q thay vì enter, p sẽ kết thúc. Chúng ta sẽ không quan tâm đến các dòng quá dài. Ngoài ra, khi hiển thị nhiều file cùng lúc thì nội dung các file sẽ được in ra liên tục mà không có sự phân cách gì cả. Tức là, đầu ra của hai lệnh sau đây là như nhau

$ p file1 file2 …

$ cat file1 file2 …  |  p

Chú ý rằng lệnh cat in ra nội dung các file một cách liên tục mà không có sự phân cách gì cả. Nếu muốn nội dung các file được phân cách bởi tên file, chúng ta có thể dùng vòng lặp sau đây (ôn lại lập trình shell luôn :-D )

$ for i in filenames
> do
>      echo $i:
>      cat $i
> done  |  p

Có rất nhiều tính năng có thể được đưa vào chương trình p. Quan điểm của chúng ta là: Trước hết tạo ra một phiên bản đơn giản, sau đó dần dần thêm vào các tính năng phức tạp hơn khi cần thiết. Những tính năng được thêm vào phải là những cái mà người dùng thực sự muốn, chứ không phải những cái mà chúng ta nghĩ rằng họ muốn.

2. Phiên bản đầu tiên của p

Cấu trúc của p cũng tương tự như vis: Hàm main duyệt qua các file đầu vào và gọi một hàm tên là print để xử lí từng file. Dưới đây là hàm main

(more…)

Unix programming with standard I/O (1)

Posted in C/C++, Unix/Linux/BSD by kiennguyen on January 17, 2008

Lời tựa

Dạo này đang thời kì nông nhàn nên quay lại với blog. Gần một tháng nay không có bài viết mới nào, có lẽ do các blogger đều đang bận bịu với những kế hoạch riêng của mình. Dạo này không thích những thứ loằng ngoằng phức tạp nữa, cũng chả thích mình là guru nữa, đau đầu lắm :-D . Bây giờ chỉ thích những thứ đơn giản nhưng đẹp đẽ. Ngẫm ra làm phần mềm cũng chẳng cần đến những thứ cao siêu hay phức tạp, vấn đề chỉ là kết hợp những thứ thật đơn giản thành một hệ thống lớn làm việc được mà thôi.

Đấy là lí do mà dạo này “tác giả” quay sang đọc cuốn “The Unix programming environment” của Brian W.Kernighan và Rob Pike. Công nhận hai bác này viết sách cực hay. Cuốn sách không chỉ trình bày các công cụ hay ngôn ngữ mà quan trọng hơn là nêu bật lên được triết lí của Unix: Viết các chương trình đơn giản, mỗi chương trình chỉ làm một nhiệm vụ nhưng có khả năng tương tác tốt với nhau để thực hiện những nhiệm vụ phức tạp hơn.

“Tác giả” bài viết này, trong thời gian tạm thời chưa bị phân tâm bởi việc fix bug nhàm chán thường nhật, muốn trích ra đây một số phần của cuốn sách, vừa để giải trí, vừa để ôn lại C và Unix, cũng vừa là để học tập tư duy lập trình trên Unix. Đồng thời, việc làm này cũng khôi phục lại phần nào tình cảm của “tác giả” đối với công việc lập trình, vốn đã bị phai nhạt khá nhiều sau một thời gian làm việc trong một dự án chán ngắt và không hề thể hiện được một chút gì gọi là “vẻ đẹp” của lập trình Unix.

Tác giả cũng khuyến cáo các độc giả (nếu có :-D ) nên tìm đọc bản tiếng Anh của cuốn sách (tác giả cũng không có bản mềm, chỉ có bản cứng), bởi trình độ kĩ thuật và tiếng Anh của tác giả đều chỉ ở mức sơ cấp.

Loạt bài viết này trích ra từ các chương 6, 7, 8, 9 của cuốn “The Unix programming environment”. Các chương này trình bày quá trình phát triển một số chương trình đơn giản, qua đó làm nổi bật lên các kĩ thuật và các triết lí lập trình trên Unix. Các chương trình này, theo tác giả cuốn sách, đều là các chương trình nhỏ và không có mặt trong 7th Edition của Unix. Nếu hệ điều hành hiện thời của bạn cũng không có chúng, bạn sẽ thấy chúng rất có ích. Trong trường hợp ngược lại, việc so sánh thiết kế của những chương trình sẵn có với những chương trình trong sách cũng mang lại nhiều điều bổ ích.

Chúng ta cùng bắt đầu với các chương trình nhập xuất dữ liệu (I/O).

Phần 1 Chương trình in ra các kí tự đặc biệt: VIS

1. Standard input and output: vis

Rất nhiều chương trình đọc dữ liệu từ một đầu vào và ghi dữ liệu ra một đầu ra. Khi đó việc sử dụng các thao tác vào ra (I/O) đối với đầu vào chuẩn (standard input) và đầu ra chuẩn (standard output) là đủ đáp ứng yêu cầu của chương trình.
Chúng ta hãy bắt đầu xây dựng một chương trình đơn giản tên là vis (viết tắt của visible). vis sao chép dữ liệu từ standard input sang standard output, đồng thời hiển thị tất cả các kí tự vốn không thể in được (non-printing character) dưới dạng \nnn, trong đó nnn là giá trị octal của kí tự đó. Ví dụ: Chúng ta chuẩn bị file đầu vào x như sau:

$ cat x
abc
def

Sử dụng vis để hiện thị x, kí tự ctrl-a sẽ được hiển thị là 01, kí tự ctrl-b sẽ được hiển thị là 02.

$ vis x
abc01
def02

Chương trình vis sẽ có ích trong việc phát hiện các kí tự lạ được ghi vào file vì một lí do nào đó. Chú ý rằng phiên bản đầu tiên của vis sẽ chỉ nhận dữ liệu vào từ standard input chứ chưa có khả năng đọc file. Khi cần in ra nội dung của nhiều file, chúng ta có thể nhờ đến lệnh cat như sau:

$ cat file1 file2 file3 … | vis

Chương trình vis của chúng ta sẽ có chức năng giống với lệnh sed sau đây:

$ sed –n l x
abc1
def2

Tuy nhiên trong một số trường hợp sed chỉ làm việc được với các file văn bản (text), bởi vậy việc viết mới chương trình vis vẫn là cần thiết.

Trong phiên bản đầu tiên của vis, chúng ta sử dụng hai hàm getchar và putchar. Hàm getchar đọc vào kí tự tiếp theo từ standard input (mặc định là terminal, cũng có thể là một file hay một pipeline, các chương trình không biết điều đó). Hàm putchar ghi một kí tự ra standard output, mặc định cũng là terminal.

Dưới đây là phiên bản đầu tiên của vis

(more…)

So sánh C++ và C (1) – Classes and methods

Posted in C/C++ by Hoang Tran on December 21, 2007

Bài viết này là một trong hai bài viết so sánh giữa C và C++ bằng cách so sánh các đoạn mã trong C++ với đoạn mã tương ứng của nó được viết trong C. So sánh này sẽ cho bạn cái nhìn tốt hơn về sự khác biệt của performance giữa C và C++.

Trong bài viết đầu tiên, chúng ta sẽ xem xét ảnh hưởng tới performance của việc thực thi các phương thức trong C++. So sánh này được thực hiện bằng việc so sánh đoạn mã C++ và đoạn mã C tương ứng.

(more…)

Tagged with:

nested class, nested function và một ứng dụng thú vị của function object

Posted in C/C++ by kiennguyen on December 20, 2007

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à:

(more…)