© Dương Thiên Tứ www.codeschool.vn Lời nói đầu Tài liệu viết với mục tiêu: - Dùng giáo trình mơn học Lập trình Hướng đối tượng với ngôn ngữ C++ Tại trường chuyên Công nghệ Thông tin, mơn học học sau mơn Lập trình với ngôn ngữ C, nên giả định bạn đọc biết sử dụng ngôn ngữ C - Nội dung tài liệu tập trung vào Lập trình Hướng đối tượng, khơng phải trình bày ngơn ngữ C++ Vì vậy, tài liệu bỏ qua số vấn đề C++: template, container, thư viện STL - Thể ngôn ngữ ANSI C++ chuẩn, dù có ghi C++11 chưa dùng đến chuẩn C++11 Các ví dụ đáp án tập viết với phong cách lập trình đặc thù C++ chuẩn, dễ tiếp cận với bạn đọc nắm vững ngôn ngữ C - Dùng tập mơn học Lập trình Hướng đối tượng Các tập xếp hợp lý, trực quan, đa dạng, số lượng đủ nhiều để bạn đọc rèn luyện kỹ (65 lớp) Các tập có đáp án cẩn thận, chi tiết Tơi xin tri ân đến bà nuôi dạy tôi, thầy tận tâm dạy tơi Chỉ có cống hiến cho tri thức tơi thấy đền đáp cơng ơn Tơi đặc biệt gửi lời cảm ơn chân thành đến anh Huỳnh Văn Đức, anh Lê Gia Minh; làm việc chung học tập anh nhiều anh giảng dạy mơn Lập trình Hướng đối tượng Đại Học Kỹ thuật Cơng nghệ Thành phố Hồ Chí Minh Tơi xin cảm ơn gia đình hy sinh nhiều để tơi có khoảng thời gian cần thiết thực tài liệu Mặc dù dành nhiều thời gian công sức cho tài liệu này, phải hiệu chỉnh chi tiết nhiều lần, tài liệu tránh sai sót hạn chế Tơi thật mong nhận ý kiến góp ý từ bạn đọc để tài liệu hồn thiện Các bạn đồng nghiệp có sử dụng giáo trình này, xin gửi cho tơi ý kiến đóng góp phản hồi, giúp giáo trình hồn thiện thêm, phục vụ cho cơng tác giảng dạy chung Phiên Cập nhật ngày: 20/10/2016 Thông tin liên lạc Mọi ý kiến câu hỏi có liên quan xin vui lòng gởi về: Dương Thiên Tứ 91/29 Trần Tấn, P Tân Sơn Nhì, Q Tân Phú, Thành phố Hồ Chí Minh Facebook: https://www.facebook.com/tu.duongthien E-mail: thientu2000@yahoo.com Trung tâm: CODESCHOOL – http://www.codeschool.vn Fanpage: https://www.facebook.com/codeschool.vn © Dương Thiên Tứ www.codeschool.vn Khai báo định nghĩa lớp Class – Declaration & Definition I Khái niệm Lập trình hướng đối tượng Lập trình hướng thủ tục (POP – Procedure-Oriented Programming) đặc trưng cách tiếp cận: - Thiết kế từ xuống (top-down design): phân rã vấn đề thành thủ tục nhỏ, tập trung vào chức chương trình - Dữ liệu + thuật tốn chương trình: tổ chức thực thủ tục theo lưu đồ để giải vấn đề Tuy nhiên, chương trình trở nên lớn phức tạp hơn, lập trình hướng thủ tục có điểm yếu: - Các hàm truy xuất khơng giới hạn đến liệu tồn cục (global), khó kiến trúc thay đổi chương trình - Sự tách biệt liệu hàm gây khó khăn mơ giới thật, nơi đối tượng có thuộc tính hành vi liên quan với Vì xuất cách tiếp cận lập trình gọi lập trình hướng đối tượng (OOP – Object-Oriented Programming) OOP phân rã vấn đề cần giải thành lớp/đối tượng, xây dựng thuộc tính (dữ liệu) hành vi (phương thức) gắn liền với đối tượng Chương trình cho đối tượng tương tác với theo kịch để giải vấn đề OOP có ưu điểm: - Thừa kế tính tốt lập trình hướng thủ tục thêm vào số khái niệm - Cung cấp cách suy nghĩ, tổ chức, phát triển chương trình dựa đối tượng, gần gũi với giới thật - Khả đóng gói giúp che giấu thơng tin làm hệ thống an tồn tin cậy - Khả thừa kế cho phép tái sử dụng dễ dàng, hệ thống có tính mở cao OOP kết hợp ba kỹ thuật chính, thường gọi tam giác P.I.E: - Encapsulation (đóng gói): liệu phương thức liên kết đơn vị gọi lớp (class) Không thể truy cập liệu từ bên ngồi mà phải thơng qua phương thức đóng gói lớp - Inheritance (thừa kế): liệu phương thức lớp thừa kế để tạo lớp mới, hình thành phân cấp lớp Điều cung cấp khả tái sử dụng, bổ sung hiệu chỉnh lớp mà khơng cần sửa đổi - Polymorphism (đa hình): khái qt hóa lớp cụ thể có liên quan với thành lớp chung để đáp ứng thơng điệp chung Tính đa hình đặc điểm đáp ứng thơng điệp chung hình thức khác tùy theo lớp cụ thể gọi Đối tượng (object) Bước hướng tới việc giải vấn đề phân tích Trong OOP, phân tích bao gồm xác định mơ tả đối tượng xác định mối quan hệ chúng Mô tả đối tượng nhằm rút đặc điểm chung để trừu tượng hóa chúng thành lớp Một đối tượng (object) thể thực thể (vật lý hay khái niệm) giới thực Một đối tượng có khía cạnh: định danh (identity), trạng thái (state), hành vi (behavior) - Identity: định danh thể tồn đối tượng Đối tượng có địa cấp phát nhớ liên kết với nó, có tên khai báo người lập trình hệ thống - State: trạng thái đối tượng, bao gồm tập thuộc tính (attribute) đối tượng trị chúng thời điểm Các thuộc tính tên liệu dùng mô tả trạng thái đối tượng Trị thuộc tính, tức trạng thái đối tượng, thay đổi q trình thực thi chương trình - Behavior: hành vi đối tượng, định tác vụ (operation) mà đối tượng thực Các tác vụ cài đặt thành phương thức (method) đối tượng Có thể dùng tác vụ để xem xét thay đổi trạng thái đối tượng Đóng gói thành lớp Car Thể sportCar thuộc lớp kết trừu tượng hóa Car dùng chương trình sportCar : Car Car – dateWhenBuild = 2005 – capacity = 300 – chassisNumber = "12143" – dateWhenBuild: int – capacity: int – chassisNumber: string + run() + brake() + turnoff() instantiation + run() + brake() + turnoff() abstraction: trạng thái + hành vi Một đối tượng Car giới thực Lớp (class) thể (instance) lớp Một lớp mơ tả tập hợp đối tượng có chung kiểu Có thể hiểu lớp kiểu chung nhóm đối tượng, kết trừu tượng hóa nhóm đối tượng thành kiểu chung - Thuộc tính khai báo liệu thành viên (data member) lớp - Hành vi khai báo cài đặt phương thức thành viên (method member) lớp Các phương thức giống hàm (có tên, danh sách đối số, trị trả về, …), liên kết với đối tượng định, nghĩa gọi thông qua đối tượng Theo cách gọi lập trình hướng thủ tục, ta thường gọi phương thức thành viên hàm thành viên © Dương Thiên Tứ www.codeschool.vn Lớp khuôn mẫu để sinh thể (instance) lớp Một lớp định nghĩa thuộc tính tác vụ hỗ trợ thể thuộc lớp Như hai thể lớp sẽ: - Có thuộc tính, trị thuộc tính khác nhau, nghĩa trạng thái chúng khác - Có hành vi, hành vi cho kết khác kết tùy thuộc vào trạng thái đối tượng Cú pháp khai báo lớp: class ; khai báo kiểu tên lớp : danh sách thừa kế public: khai báo friend protected: khai báo thuộc tính private: khai báo phương thức { danh sách instance ; { thân hàm inline } } Cú pháp khai báo thuộc tính lớp: const kiểu static tên thuộc tính , Trong định nghĩa lớp ta phân định phạm vi truy xuất thành viên lớp bổ từ truy xuất (access modifier): private, public protected Ví dụ định nghĩa lớp tập tin tiêu đề (header file): // account.h // khai báo lớp Account #ifndef _ACCOUNT_ // tránh khai báo (include) nhiều lần #define _ACCOUNT_ using std::string; class Account { public: // Thành viên thuộc giao diện công khai: bool init( long = 1111111, const string & = "N/A", double = 0.0 ); void display() const; private: // Thành viên thuộc giao diện riêng tư, bảo vệ: long code; // mã tài khoản string name; // tên chủ tài khoản double balance; // tiền tài khoản }; #endif // _ACCOUNT_ Lớp thành viên mô tả cách đồ họa cách dùng UML (Unified Modeling Language): Ký hiệu lớp thành viên: Account định danh – code: long – name: string – balance: double thuộc tính + init(c: long, s: const string{&}, b: double ): bool + display() {readOnly} hành vi Ký hiệu thể lớp, bên phải thể vô danh: account : Account : Account – code = 1234567 – name = "Pitt, Brad" – balance = 1963.75 – code = 1111111 – name = "N/A" – balance = 0.0 Ta trừu tượng hóa nhóm đối tượng chung giới thật thành lớp, tạo thể lớp chương trình để giải vấn đề Cần ý rằng: ta thường dùng từ "đối tượng" để nói đến "thể hiện" (instance) Một chương trình chạy tập đối tượng tương tác với Trừu tượng hóa liệu (data abstraction) đóng gói (encapsulation) Các khái niệm chủ yếu lập trình hướng đối tượng, đối tượng lớp, thiết kế theo nguyên tắc quan trọng sau: - Trừu tượng hóa (abstraction): Trong bước phân tích để giải vấn đề OOP, ta gom nhóm, mơ tả đối tượng phát mối quan hệ tác động chúng Kết việc mơ tả đối tượng trừu tượng hóa nhóm đối tượng chung thành lớp Một lớp xem kiểu liệu trừu tượng (ADT – abstract data type) người dùng định nghĩa, thể lớp xem biến có kiểu liệu lớp tạo Sự trừu tượng hóa liệu giúp người dùng kiểu liệu trừu tượng không © Dương Thiên Tứ www.codeschool.vn phải quan tâm đến chi tiết cài đặt bên kiểu liệu - Đóng gói (encapsulation) hay ẩn giấu thơng tin (informaton hiding): Dữ liệu thành viên lớp thường che giấu bên phần riêng tư (private) lớp, khơng truy xuất từ bên ngồi Phương thức thành viên lớp thường bộc lộ bên cách khai báo phần công khai (public) lớp Chú ý ứng dụng không cần biết cấu trúc liệu bên lớp không cần biết chi tiết cài đặt phương thức lớp Như thay đổi bên lớp thực mà không ảnh hưởng đến ứng dụng II Tạo lớp Encapsulation Encapsulation (đóng gói) kỹ thuật gom chung thuộc tính (dữ liệu) hành vi liên quan (phương thức tác động liệu đó) nhóm đối tượng vào thành lớp Để truy xuất thuộc tính hành vi lớp phải tạo thể lớp Chúng ta trừu tượng hóa đối tượng cách định nghĩa lớp Định nghĩa lớp đóng gói thuộc tính hành vi đối tượng thuộc lớp Student Information Student ID: First Name: Last Name: Graduation: Student Yes No – ID: int – firstName: string – lastName: string – graduation: bool + write(): void + display(): void Write Student Information Display Student Information Định nghĩa lớp Student đóng gói thuộc tính hành vi đối tượng thể sinh viên Mục đích chủ yếu đóng gói ẩn giấu thơng tin, bảo vệ liệu tránh khỏi truy xuất tự từ người dùng lớp Lớp phát triển từ structure, tạo lớp tạo kiểu liệu Do đó, lớp khai báo cài đặt lồng hàm cài đặt lồng lớp khác Lớp A Phân định phạm vi truy xuất Khi tổ chức tập tin cho dự án, ta tách biệt giao diện cài đặt, gọi lập trình theo khối (modular programming): - Khai báo lớp, gọi phần giao diện lớp (class interface) thường đặt tập tin h (header file) - Định nghĩa lớp, gọi phần cài đặt cho lớp (class implementation) thường đặt tập tin khác (.cpp) Khi khai báo lớp, ta phân định phạm vi truy xuất thành viên thuộc lớp, cách dùng bổ từ truy xuất (access modifier), gọi tính "thấy được" (visibility) thành viên thuộc lớp: - private: phần "riêng tư" lớp, thường thuộc tính lớp, truy xuất phương thức lớp Nếu thành viên không thuộc phần mặc định private (với structure, mặc định public) - public: phần "công khai" lớp, thường phương thức lớp khác công cộng lớp, truy xuất từ bên ngồi lớp Muốn hàm toàn cục gọi hành vi đối tượng thuộc lớp, ta truyền thông điệp đến đối tượng, nghĩa gọi phương thức bộc lộ hàm thành viên phần public hàm thành hàm friend private Phần public tạo thành giao diện công cộng lớp với bên viên lớp lớp friend ngoài, thường gọi contract (giao kết) dẫn xuất protected - protected: phần "bảo vệ" lớp, tương tự phần private, có ý nghĩa thừa kế, thảo luận public sau phần thừa kế Cần có quyền truy xuất gọi phương thức thành viên lớp Quyền truy xuất mô tả bảng bên dưới, số chi tiết bảng thảo luận sau Lớp A Lớp dẫn xuất từ A Lớp bên ngồi Quyền truy xuất nhìn từ lớp A Phương Phương thức Phương Phương thức Phương thức Phương lớp friend thức thường thức thường thức khác public đọc đọc/ghi đọc đọc/ghi đọc/ghi đọc/ghi protected Thuộc tính đọc đọc/ghi đọc đọc/ghi đọc/ghi private đọc đọc/ghi đọc/ghi public gọi gọi gọi gọi gọi gọi Phương protected gọi gọi gọi gọi gọi thức private gọi gọi gọi public gọi gọi gọi gọi Phương protected gọi gọi gọi thức thường private gọi gọi Định nghĩa phương thức thành viên Khi định nghĩa phương thức lớp bên định nghĩa lớp, ta định nghĩa giống định nghĩa hàm tồn cục, khơng cần tên lớp kèm theo Cú pháp khai báo phương thức khai báo lớp: © Dương Thiên Tứ www.codeschool.vn const kiểu trả ( static virtual const tên phương thức kiểu tên đối số trị mặc định = ) const , Khi định nghĩa phương thức lớp bên định nghĩa lớp, phải cung cấp tên lớp trước tên phương thức, cách biệt với tên phương thức toán tử phân định phạm vi (scope resolution) "::" Cú pháp định nghĩa phương thức bên khai báo lớp: kiểu trả ( const kiểu , tên lớp :: tên đối số ) const { thân phương thức } tên phương thức Bên phương thức thành viên, truy cập trực tiếp tất thành viên khác lớp (dữ liệu phương thức) cách gọi tên chúng // account.cpp // định nghĩa lớp Account #include "account.h" // bao gồm tập tin tiêu đề chứa định nghĩa lớp #include #include using namespace std; // cài đặt phương thức init() khởi tạo liệu thành viên lớp // sau thay constructor bool Account::init( long c, const string & s, double b ) { if ( s.empty() ) return false; code = c; name = s; balance = b; return true; } // cài đặt phương thức display() hiển thị liệu thành viên void Account::display() const { cout display(); // dùng toán tử "->" return 0; Con trỏ this Bên lớp, phương thức thành viên truy xuất trực tiếp đến thành viên khác đối tượng hành mà không cần thông qua tên đối tượng Phương thức biết đối tượng hành làm việc với nó, phương thức gọi, đối số ẩn chứa địa đối tượng hành truyền đến phương thức Địa chứa sẵn trỏ gọi trỏ this Như vậy, phương thức thành viên tồn đối số ẩn (đối số thứ nhất), trỏ this đối tượng lưu trữ liệu thành viên nhớ bill : Student – – – – ID = 1200 firstname = "Bill" lastname = "Gates" graduation = false + display() : void james : Student – – – – ID = 1500 firstname = "James" lastname = "Gosling" graduation = true lời gọi hàm bill.display() trình biên dịch hiểu display( &bill ) nên hàm display() hiển thị xác liệu thành viên bill đối tượng dùng chung hàm thành viên, hàm thành viên có đối số ẩn trỏ this Trình biên dịch hiểu là: display( Student* this ) Con trỏ this từ khóa, trỏ đến đối tượng hành, cho phép tham chiếu đối tượng hành cần #include using namespace std; class Student { public: Student( int id, string fname, string lname, bool g ) : ID( id ), firstName( fname ), lastName( lname ), graduation( g ) { } void display() const { // dùng trỏ ẩn this để truy xuất đến liệu thành viên Tuy nhiên không cần thiết cout