Xem mẫu

  1. BỘ GIAO THÔNG VẬN TẢI TRƢỜNG ĐẠI HỌC HÀNG HẢI BỘ MÔN: KHOA HỌC MÁ Y TÍ NH KHOA: CÔNG NGHỆ THÔNG TIN BÀI GIẢNG LẬP TRÌNH HƢỚNG ĐỐI TƢỢNG VÀ C++ TÊN HỌC PHẦN : Lập trình hƣớng đối tƣợng và C++ MÃ HỌC PHẦN : 17209 TRÌNH ĐỘ ĐÀO TẠO : ĐẠI HỌC CHÍNH QUY DÙNG CHO SV NGÀNH : CÔNG NGHỆ THÔNG TIN HẢI PHÒNG - 2008
  2. Mô tả vắn tắt nội dung và khối lượng học phần Tên học phần: Lập trình hướng đối tượng và C++. Loại học phần : 2 Bộ môn phụ trách giảng dạy: Khoa học máy tính. Khoa phụ trách: CNTT Mã học phần: 17209 Tổng số TC: 4 TS tiết Lý thuyết Thực hành/ Xemina Tự học Bài tập lớn Đồ án môn học 75 45 30 0 0 0 Điều kiện tiên quyết: Sinh viên phải học và thi đạt các học phần sau mới được đăng ký học học phần này: Kỹ thuật lập trình Pascal, Kỹ thuật lập trình C. Mục tiêu của học phần: Cung cấp kiến thức của phương pháp lập trình hướng đối tượng và rèn luyện kỹ năng lập trình . Nội dung chủ yếu: - Những mở rộng của lập trình hướng đối tượng. - Đối tượng và lớp. - Đóng gói, thừa kế, đa hình. - Bản mẫu, thư viện STL Nội dung chi tiết: PHÂN PHỐI SỐ TIẾT TÊN CHƢƠNG MỤC TS LT Thực hành BT KT Chƣơng 1: Lâ ̣p trin ̀ h hướng đố i tươ ̣ng và 3 3 ngôn ngữ C++ 1.1 Ưu điểm của lập trình hướng đối tượng 1.2 Giới thiệu ngôn ngữ C++ Chƣơng 2: Những khái niê ̣m mở đầ u 9 6 3 2.1 Cài đặt ngôn ngữ C++ 2.2 Cấu trúc một chương trình C++ 2.3 Kiểu dữ liệu cơ sở 2.4 Quy tắc sử dụng từ khóa, tên chuẩn, tên từ đặt. 2.5 Các chỉ thị gán, so sánh, điều kiện nếu thì .. Chƣơng 3: Con trỏ, tham chiế u và hàm 6 3 3 3.1 Khai báo hàm con, hàm chính. 3.2 Quy tắc đổi kiểu dữ liệu, kiểu trỏ. 3.3 Định nghĩa chồng hàm, tham số ngầm định.. 3.5 Tham chiểu. Chƣơng 4: Các dòng vào ra trong C++ 9 5 3 1 4.1 Đối tượng vào ra cout, cin 4.2 Đẩy dòng dữ liệu lên màn hình 4.3 Nhập dòng dữ liệu từ bàn phím 4.4 Định dạng dòng dữ liệu hiển thị 4.5 Vào ra với tệp Chƣơng 5: Đối tượng và Lớp 18 8 9 1 i
  3. 5.1 Định nghĩa đối tượng 5.2 Khai báo lớp 5.3 Hàm thiết lập, huỷ bỏ 5.4 Thành phần tĩnh, hàm bạn, lớp bạn 5.5 Định nghĩa chồng toán tử Chƣơng 6: Thừa kế 9 6 3 6.1 Lớp cơ sở, lớp dẫn xuất 6.2 Quy tắc thừa kế 6.3 Tương thích lớp cơ sở và lớp dẫn xuất 6.4 Đơn thừa kế, đa thừa kế Chƣơng 7: Ràng buộc động và Đa thể 8 5 3 7.1 Hàm ảo, ràng buộc tĩnh, động 7.2 Đa thể Chƣơng 8: Bản mẫu 13 6 6 1 8.1 Hàm bản mẫu 8.2 Ưu khuyết điểm của hàm bản mẫu 8.3 Lớp bản mẫu Nhiệm vụ của sinh viên: Lên lớp đầy đủ và chấp hành mọi quy định của Nhà trường. Tài liệu học tập: 1. Tên tác giả. Tên sách. Nhà xuất bản. Năm xuất bản. 2. Phạm Văn Ất. Kỹ thuật lập trình hướng đối tượng. NXB KHKT. 1998 3. Một số website liên quan. Hình thức và tiêu chuẩn đánh giá sinh viên: - Thi viết hoặc thi thực hành. - Sinh viên phải bảo đảm các điều kiện theo Quy chế của Nhà trường và của Bộ. Thang điểm : Thang điểm chữ A,B,C,D,F. Điểm đánh giá học phần: Z=0,3X+0,7Y. Bài giảng này là tài liệu chính thức và thống nhất của Bộ môn Khoa học Máy tính, Khoa Công nghệ Thông tin và được dùng để giảng dạy cho sinh viên. Ngày phê duyệt: / /20 Trƣởng Bộ môn: ThS. Nguyễn Hữu Tuân (ký và ghi rõ họ tên) ii
  4. MỤC LỤC CHƢƠNG I: LẬP TRÌ NH HƢỚNG ĐỐI TƢỢNG VÀ NGÔN NGỮ C++ ................... 1 1. Sự phát triển của các kỹ thuật lập trình.......................................................................... 1 1.1 Lâ ̣p triǹ h không có cấ u trúc (hay lâ ̣p triǹ h tuyế n tiń h) ............................................ 1 1.2 Lâ ̣p trình thủ tu ̣c hay lâ ̣p trình có cấ u trúc ............................................................... 1 1.3 Lâ ̣p triǹ h module ...................................................................................................... 3 1.4 Lâ ̣p triǹ h hướng đố i tượng ....................................................................................... 4 2. Mô ̣t số khái niê ̣m cơ bản của lập trình hướng đố i tượng ............................................... 5 2.1 Kiể u dữ liê ̣u trừu tượng ADT(Astract Data Type) .................................................. 5 2.2 Đối tượng (Objects) và lớp (Classes) ...................................................................... 5 2.3 Kế thừa (Inheritance) ............................................................................................... 6 2.4 Dynamic Binding (ràng buộc động) và Porlymorphism (đa xa ̣ hoă ̣c đa thể ) .......... 6 3. Ngôn ngữ lâ ̣p triǹ h C++ và OOP. .................................................................................. 7 3.1 Sự phát triển của các ngôn ngữ lâ ̣p triǹ h hướng đố i tượng...................................... 7 3.2 Ngôn ngữ lâ ̣p trình C++. .......................................................................................... 8 4. Bài tập ............................................................................................................................ 8 CHƢƠNG II: NHỮNG KHÁI NIỆM MỞ ĐẦU .............................................................. 9 1. Chương trình đầ u tiên .................................................................................................... 9 1.1 Quá trình biên dịch một chương triǹ h C++ ............................................................. 9 1.2 Chương triǹ h đầ u tiên. ........................................................................................... 13 2. Biế n, hằ ng và tầ m hoa ̣t đô ̣ng của các biế n ................................................................... 15 2.1 Cú pháp khai báo biến (variable declaration) ........................................................ 15 2.2 Tầ m hoa ̣t đô ̣ng của các biế n .................................................................................. 16 2.3 Khai báo biế n ngay trong cú pháp của các câu lê ̣nh điề u khiể n ............................ 16 2.4 Các kiểu biến ......................................................................................................... 17 2.5 Liên kế t biế n khi biên dich ̣ .................................................................................... 18 2.6 Các hằng ................................................................................................................ 18 3. Hàm trong C++ ............................................................................................................ 19 4. Các cấu trúc điều khiển ................................................................................................ 20 4.1 Câu lê ̣nh if-else ...................................................................................................... 20 4.2 Vòng lặp không xác định while ............................................................................. 20 4.3 Vòng lặp không xác định do – while ..................................................................... 21 4.4 Vòng lặp xác định for ............................................................................................ 21 4.5 Các từ khóa break và continue ............................................................................... 22 4.6 Câu lê ̣nh lựa cho ̣n switch ....................................................................................... 22 4.7 Câu lê ̣nh goto ......................................................................................................... 23 4.8 Đệ qui ..................................................................................................................... 23 iii
  5. 5. Các kiểu dữ liê ̣u cơ bản của C++ ................................................................................. 23 6. Mô ̣t số toán tử trong C++ ............................................................................................ 25 6.1 Toán tử gán (assignment operator) ........................................................................ 25 6.2 Các toán tử toán học .............................................................................................. 25 6.3 Các toán tử quan hê ̣................................................................................................ 25 6.4 Các toán tử logic .................................................................................................... 26 6.5 Các toán tử bitwise ................................................................................................ 26 6.6 Các toán tử dịch ..................................................................................................... 26 6.7 Các toán tử mô ̣t ngôi .............................................................................................. 26 6.8 Toán tử 3 ngôi ........................................................................................................ 26 6.9 Toán tử dấ u phẩ y .................................................................................................... 27 6.10 Các lỗi thường gă ̣p khi sử dụng các toán tử......................................................... 27 6.11 Toán tử chuyể n kiể u ............................................................................................. 27 6.12 Toán tử sizeof. ...................................................................................................... 28 7. Các kiểu dữ liê ̣u người dùng đinh ̣ nghiã ...................................................................... 28 8. Bài tập .......................................................................................................................... 31 CHƢƠNG III: CON TRỎ, THAM CHIẾU VÀ HÀ M................................................... 34 1. Hàm trong C++ ............................................................................................................ 34 1.1 Nguyên mẫu và đinh ̣ nghĩa hàm ............................................................................ 34 1.2 Hàm và các biến ..................................................................................................... 34 1.3 Truyề n tham số ...................................................................................................... 34 1.4 Chồ ng hàm (overload) và tham số mặc định của hàm ........................................... 35 1.5 Các vấn đề khác ..................................................................................................... 36 2. Con trỏ, hàm và mảng .................................................................................................. 37 3. Hàm và xử lý xâu ......................................................................................................... 38 4. Bài tập .......................................................................................................................... 38 CHƢƠNG IV: CÁC DÒNG VÀO RA TRONG C++ ..................................................... 40 1. Tổ ng quan về các luồ ng vào ra của C++ ..................................................................... 40 2. Các luồng và các bộ đệm ............................................................................................. 41 3. Các đối tượng vào ra chuẩ n ......................................................................................... 41 4. Đinh ̣ hướng la ̣i (Redirection) ....................................................................................... 41 5. Nhâ ̣p dữ liê ̣u với cin .................................................................................................... 42 6. Các hàm thành viên khác của cin ................................................................................. 42 7. Kế t xuấ t dữ liê ̣u với cout ............................................................................................. 45 8. Các dòng vào ra và hàm printf ..................................................................................... 46 9. Vào ra dữ liê ̣u với các file ............................................................................................ 46 10. File text và file nhi ̣phân ............................................................................................ 48 iv
  6. 11. Tìm kiếm trong các dòng vào ra ................................................................................ 48 12. stringstream ................................................................................................................ 49 13. Bài tập ........................................................................................................................ 52 CHƢƠNG V: ĐỐI TƢỢNG VÀ LỚP. ............................................................................. 54 1. Trừu tượng dữ liê ̣u ....................................................................................................... 54 2. Thế nào là mô ̣t đố i tượng? ........................................................................................... 54 3. Các lớp và các đố i tượng ............................................................................................. 55 4. Con trỏ và mảng các đố i tượng .................................................................................... 58 5. Khai báo các lớp với các file header ............................................................................ 59 6. Kiể m soát viê ̣c truy câ ̣p tới các biế n và phương thức của lớp ..................................... 61 7. Các hàm bạn và các lớp ba ̣n ........................................................................................ 62 8. Con trỏ this................................................................................................................... 66 9. Khởi ta ̣o các đố i tượng của lớp thông qua các hàm cấ u tử .......................................... 67 10. Hủy tử ........................................................................................................................ 72 11. Cấ u tử copy ................................................................................................................ 76 12. Đối tượng hằ ng và các hàm thành viên hằ ng ............................................................. 78 13. Các thành viên tĩnh của lớp ....................................................................................... 79 14. Sử dụng các đối tượng trong vai trò là tham số của hàm........................................... 80 15. Các đối tượng chồ ng nhau: Các lớp là thành viên của các lớp khác. ........................ 82 16. Chồ ng toán tử............................................................................................................. 84 17. Bài tập ........................................................................................................................ 91 CHƢƠNG VI: KẾ THỪA (INHERITANCE)................................................................. 94 1. Sử dụng lại mã chương triǹ h........................................................................................ 94 2. Sử dụng lại mã chương triǹ h trong OOP ..................................................................... 94 3. Cú pháp kế thừa ........................................................................................................... 94 4. Đinh ̣ nghĩa lại các thành viên của lớp cơ sở ................................................................ 96 5. Kiể m soát truy câ ̣p ....................................................................................................... 98 6. Các kiểu kế thừa......................................................................................................... 101 6.1 Kế thừa public ...................................................................................................... 101 6.2. Kế thừa private.................................................................................................... 101 6.3 Kế thừa protected ................................................................................................. 102 7. Đinh ̣ nghiã la ̣i các đă ̣c tả truy câ ̣p .............................................................................. 102 8. Các hàm không thể kế thừa........................................................................................ 103 9. Các hàm cấu tử và kế thừa ......................................................................................... 103 10. Composition và Inheritance ..................................................................................... 105 11. Đa kế thừa ................................................................................................................ 107 12. Lă ̣p la ̣i lớp cơ sở trong đa kế thừa và lớp cơ sở ảo .................................................. 108 v
  7. 13. Con trỏ và các đố i tượng .......................................................................................... 109 14. Con trỏ và kế thừa .................................................................................................... 116 15. Bài tập ...................................................................................................................... 117 CHƢƠNG VII: RÀNG BUỘC ĐỘNG VÀ ĐA THỂ ................................................... 118 1. Mô ̣t số đă ̣c điể m của ràng buô ̣c đô ̣ng và đa thể ......................................................... 118 1.1 Ràng buộc động ................................................................................................... 118 1.2 Đa thể - Polymorphism ....................................................................................... 118 2. Các hàm thành viên bình thường được truy câ ̣p qua các con trỏ ............................... 119 3. Các hàm thành viên ảo được truy câ ̣p qua các con trỏ .............................................. 120 4. Ràng buộc động ......................................................................................................... 122 4.1 Ràng buộc động làm việc như thế nào ................................................................. 122 4.2 Không sử dụng con trỏ this .................................................................................. 124 5. Danh sách liên kế t các đố i tượng và đa thể ............................................................... 124 6. Các lớp trừu tượng – abstract class ............................................................................ 128 7. Các hàm ảo thực sự .................................................................................................... 129 7.1 Ví dụ 1 ................................................................................................................. 129 7.2 Ví dụ 2 ................................................................................................................. 131 8. Cấ u tử ảo và hủy tử ảo ............................................................................................... 135 9. Hàm toán tử ảo ........................................................................................................... 136 10. Bài tập ...................................................................................................................... 139 CHƢƠNG VIII: BẢN MẪU (TEMPLATE) ................................................................. 140 1. Các lớp bản mẫu ........................................................................................................ 140 1.1 Các bản mẫu và thể nghiệm ................................................................................. 141 1.2 Các thành phần tĩnh ............................................................................................. 146 1.3 Các lớp ba ̣n và lớp trợ giúp.................................................................................. 147 1.4 Các tham số bản mẫu ........................................................................................... 149 1.5 Các lớp thuô ̣c tiń h ................................................................................................ 151 1.6 Các lớp chứa (bản mẫu) chuẩ n ............................................................................ 154 2. Các hàm bản mẫu ....................................................................................................... 154 2.1 Các định nghĩa và thể nghiệm .............................................................................. 154 2.2 Các hàm chuẩn chung – thư viê ̣n thuâ ̣t toán ........................................................ 157 3. Bài tập ........................................................................................................................ 157 TÀI LIỆU THAM KHẢO ............................................................................................... 158 ĐỀ THI THAM KHẢO ................................................................................................... 159 vi
  8. CHƢƠNG I: LẬP TRÌ NH HƢỚNG ĐỐI TƢỢNG VÀ NGÔN NGƢ̃ C++ 1. Sƣ ̣ phát triể n của các kỹ thuâ ̣t lâ ̣p trin ̀ h Phầ n này trình bày về mô ̣t số kỹ thuâ ̣t hay p hương pháp lâ ̣p trình đươ ̣c phát triể n để giải quyết các vấn đề trong Tin học kể từ khi máy tính ra đời . Sự phát triể n của các kỹ thuâ ̣t lâ ̣p triǹ h liên quan chă ̣t chẽ tới sự phát triể n phầ n cứng của máy vi tiń h cũng như v iê ̣c ứng dụng máy tính vào giải quyết các vấn đề trong thực tế . Chúng ta có thể chia các phương pháp lập trình thành các kiểu sau: + Lâ ̣p triǹ h không có cấ u trúc + Lâ ̣p triǹ h hướng thủ tu ̣c + Lâ ̣p trình theo kiể u module hóa + Lâ ̣p trình hướng đố i tươ ̣ng Chúng ta sẽ lần lượt xem xét các kỹ thuật lập trình này. 1.1 Lâ ̣p trin ̀ h không có cấ u trúc (hay lâ ̣p trin ̀ h tuyế n tính) Thông thường mo ̣i người bắ t đầ u ho ̣c lâ ̣p trình bằ ng cách viế t các chương trình nhỏ và đơn giản chỉ chứa một “chương trình chính” . Ở đây một chương trình chính có nghĩa là mô ̣t tâ ̣p các lê ̣nh hoă ̣c câu lê ̣nh làm viê ̣c với các dữ liê ̣u toàn cu ̣c trong cả chương triǹ h (các biế n dùng trong chương triǹ h là các biến toàn cục). Chúng ta có thể minh hoạ bằng hình vẽ sau đây: Lâ ̣p trin ̀ h không có cấ u trúc. Chƣơng trin ̀ h chính thao tác trƣ̣c tiế p trên các dƣ̃ liêụ toàn cu ̣c Mô ̣t số nhươ ̣c điể m của lâ ̣p triǹ h không có cấ u trúc: + Lâ ̣p trình không có cấ u trúc không có khả năng kiể m soát tính thấ y đươ ̣c của dữ liê ̣u. Mọi dữ liệu trong chương trình đều là biến toàn cục do đó có thể bị thay đổi bởi bất kỳ phần nào đó của chương trình. + Viê ̣c không kiể m soát đươ ̣c tiń h thấ y đươ ̣c của dữ liê ̣u dẫn đế n các khó khăn trong viê ̣c gỡ lỗi chương triǹ h, đă ̣c biê ̣t là các chương triǹ h lớn. + Kỹ thuật lập trình không có cấu trúc có rất nhiều bất lợi lớn khi chương trình đủ lớn. Ví dụ nếu chúng ta cần thực hiện lại một đoạn câu lệnh trên một tập dữ liệu khác thì buô ̣c phải copy đoa ̣n lê ̣nh đó tới vi ̣trí trong chương triǹ h mà chúng ta muố n thực hiê ̣n . Điề u này làm nảy sinh ý tưởng trích ra các đo ạn lệnh thường xuyên cần thực hiện đó , đă ̣t tên cho chúng và đưa ra mô ̣t kỹ thuâ ̣t cho phép go ̣i và trả về các giá tri ̣từ các thủ tu ̣c này . 1.2 Lâ ̣p trin ̀ h thủ tu ̣c hay lâ ̣p trin ̀ h có cấ u trúc Với lâ ̣p triǹ h thủ tu ̣c hay hướng thủ tục chúng ta có thể nhóm các câu lệnh thường xuyên thực hiê ̣n trong chương triǹ h chiń h la ̣i mô ̣t chỗ và đă ̣t tên đoa ̣n câu lê ̣nh đó thành 1
  9. mô ̣t thủ tu ̣c. Mô ̣t lời go ̣i tới thủ tu ̣c sẽ đươ ̣c sử du ̣ng để thực hiê ̣n đoa ̣n câu lê ̣nh đó. Sau khi thủ tục thực hiện xong điều khiển trong chương trình được trả về ngay sau vị trí lời gọi tới thủ tục trong chương trình chính . Với các cơ chế truyề n tham số cho thủ tu ̣c chúng ta có các chương trình con . Mô ̣t chươn g triǹ h chiń h bao gồ m nhiề u chương triǹ h con và các chương triǹ h đươ ̣c viế t mang tiń h cấ u trúc cao hơn , đồ ng thời cũng it́ lỗi hơn . Nế u mô ̣t chương trình con là đúng đắ n thì kế t quả thực hiê ̣n trả về luôn đúng và chúng ta khôn g cầ n phải quan tâm tới các chi tiết bên trong của thủ tục . Còn nếu có lỗi chúng ta có thể thu hẹp phạm vi gỡ lỗi trong các chương trình con chưa được chứng minh là đúng đắn , đây đươ ̣c xem như trừu tươ ̣ng hàm và là nề n tảng cho lâ ̣p triǹ h thủ tu ̣c. Mô ̣t chương trình chính với lâ ̣p trình thủ tu ̣c có thể đươ ̣c xem là tâ ̣p hơ ̣p các lời go ̣i thủ tục. Lâ ̣p trin ̀ h thủ tu ̣c. Sau khi chƣơng trin ̀ h con thƣ ̣c hiêṇ xong điề u khiể n đƣơ ̣c trả về ngay sau vi tri ̣ ́ lời go ̣i tới chƣơng trin ̀ h con Chương triǹ h chiń h có nhiê ̣m vu ̣ truyề n các dữ liê ̣u cho các lời go ̣i cu ̣ thể , dữ liê ̣u đươ ̣c xử lý cu ̣c bô ̣ trong chương trình con sau đó các kế t quả thực hiê ̣n này đươ ̣c trả về cho chương trình chính. Như vâ ̣y luồ ng dữ liê ̣u có thể đươ ̣c minh ho ̣a như là mô ̣t đồ thi ̣phân cấ p, mô ̣t cây: Lâ ̣p trin ̀ h hƣớng thủ tu ̣c. Chƣơng trin ̀ h chính phố i hơ ̣p các lời gọi tới các thủ tục với các dữ liệu thích hợp là các tham số Lâ ̣p trình hướng thủ tu ̣c là mô ̣t kỹ thuâ ̣t lâ ̣p trình có nhiề u ưu điể m . Khái niệm chương triǹ h con là mô ̣t ý tưởng rấ t hay , nó cho phép một chương trình lớn có thể được chia thành nhiề u chương triǹ h con nhỏ hơn , đo đó dễ viế t hơn và it́ lỗi hơn . Để có thể sử dụng được các thủ tục chung hoặc một nhóm các thủ tục trong các chương trình khác , người ta đã phát minh ra mô ̣t kỹ thuâ ̣t lâ ̣p trình mới , đó là kỹ thuâ ̣t lâ ̣p trình theo kiể u module. 2
  10. 1.3 Lâ ̣p trin ̀ h module Trong lâ ̣p triǹ h module các thủ tu ̣c có cùng mô ̣t chức năng chung sẽ đươ ̣c nhóm la ̣i với nhau ta ̣o thành mô ̣t module riêng biê ̣t . Mô ̣t chương triǹ h sẽ không chỉ bao gồ m mô ̣t phầ n đơn lẻ . Nó được chia thành một vài phầ n nhỏ hơn tương tác với nhau qua các lời go ̣i thủ tục và tạo thành toàn bộ chương trình. Lâ ̣p trin ̀ h module. Chƣơng triǹ h chính là sƣ̣ kế t hơ ̣p giƣ̃a các lời go ̣i tới các thủ tục trong các module riêng biệt với các dữ liệu thích hơ ̣p Mỗi module có dữ liê ̣u riêng của nó . Điề u này cho phép các module có thể kiể m soát các dữ liệu riêng của nó bằng các lời gọi tới các thủ tục trong module đó . Tuy nhiên mỗi module chỉ xuấ t hiê ̣n nhiề u nhấ t mô ̣t lầ n trong cả chương triǹ h. Yế u điể m của lâ ̣p triǹ h thủ tu ̣c và lâ ̣p triǹ h module hóa: + Khi đô ̣ phức ta ̣p của chương trình tăng lên sự phu ̣ thuô ̣c của nó vào các kiể u dữ liê ̣u cơ bản mà nó xử lý cũng tăng theo . Vấ n đề trở nên rõ ràng rằ ng cấ u trúc dữ liê ̣u sử dụng trong chương trình cũng quan trọng không kém các phép toán thực hiện trên chúng . Điề u này càng lô ̣ rõ khi kić h thước chương triǹ h tăng . Các kiểu dữ liệu được xử lý nhiều trong các thủ tu ̣c của mô ̣t chương trình có cấ u trúc . Do đó khi thay đổ i cài đă ̣t của mô ̣t kiể u dữ liê ̣u sẽ dẫn đế n nhiề u thay đổ i trong các thủ tu ̣c sử du ̣ng nó . + Mô ̣t nhươ ̣c điể m nữa là khi cầ n dùng nhiề u nhóm làm viê ̣c để xây dựng mô ̣t chương trình chung . Trong lâ ̣p trình có cấ u trúc mỗi người sẽ đươ ̣c giao xây dựng mô ̣t số thủ tục và kiểu dữ liệu . Những lâ ̣p triǹ h viên xử lý các thủ tu ̣c khác nhau nhưng la ̣i có liên quan tới các kiể u dữ liê ̣u dùng chung nên nế u mô ̣t người thay đổ i kiể u dữ liê ̣u thì sẽ làm ảnh hưởng tới công việc của nhiều người khác , đă ̣c biê ̣t là khi có sai sót trong viê ̣c liên la ̣c giữa các thành viên của nhóm . + Viê ̣c phát triể n các phầ m mề m mấ t nhi ều thời gian tập trung xây dựng lại các cấu trúc dữ liệu cơ bản . Khi xây dựng mô ̣t chương triǹ h mới trong lâ ̣p triǹ h có cấ u trúc lâ ̣p trình viên thường phải xây dựng lại các cấu trúc dữ liệu cơ bản cho phù hợp với bài toán và điề u này đôi khi rấ t mấ t thời gian. 3
  11. 1.4 Lâ ̣p trin ̀ h hƣớng đố i tƣơ ̣ng Trong lâ ̣p triǹ h hướng đố i tươ ̣ng trong mỗi chương triǹ h chúng ta có mô ̣t số các đố i tươ ̣ng (object) có thể tương tác với nhau , thuô ̣c các lớp (class) khác nhau, mỗi đố i tươ ̣ng tự quản lý lấ y các dữ liê ̣u của riêng chúng . Lâ ̣p triǹ h hướng đố i tươ ̣ng. Các đối tượng tương tác với nhau bằng cách gửi các thông điệp. Chương trình chính sẽ bao gồ m mô ̣t số đố i tươ ̣ng là thể hiê ̣n (instance) của các lớp , các đối tượng này tương tác với nhau thực hiện các chức năng của chương trình . Các lớp trong lâ ̣p triǹ h hướng đố i tươ ̣ng có thể xem như là mô ̣t sự trừu tươ ̣ng ở mức cao hơn của các cấu trúc (struct hay record) hay kiể u dữ liê ̣u do người dùng đinh ̣ nghiã trong các ngôn ngữ lâ ̣p trình có cấ u trúc với sự tích hơ ̣p cả các toán tử và dữ liê ̣u trên các kiể u đó . Các ưu điểm của lập trình hướng đối tượng: + Lâ ̣p trình hướng đố i tươ ̣ng ra đời đã giải quyế t đươ ̣c nhiề u nhươ ̣c điể m tồ n ta ̣i trong lâ ̣p triǹ h có cấ u trúc . Trong lâ ̣p triǹ h OOP có it́ lỗi hơn và viê ̣c gỡ lỗi cũng đơn giản hơn, đồ ng thời lâ ̣p triǹ h theo nhóm có thể thực hiê ̣n rấ t hiê ̣u quả . Ít lỗi là mô ̣t trong các ưu điể m chính của OOP vì theo thố ng kê thì viê ̣c bảo trì hê ̣ thố ng phầ n mề m sau khi giao cho người dùng chiế m tới 70% giá thành phần mềm. + Viê ̣c thay đổ i các cài đă ̣t chi tiế t bên dưới trong lâ ̣p triǹ h OOP không làm ảnh hương tới các phầ n khác của chương trình do đó viê ̣c mở rô ̣ng qui mô của mô ̣t chương trình dễ dàng hơn, đồ ng thời làm giảm thời gian cầ n thiế t để phát triể n phầ n mề m . + Với khái niê ̣m kế thừa các lâ ̣p trình viên có thể xây dựng các chương trình từ các phầ n mề m sẵn có. + OOP có tiń h khả chuyể n cao . Mô ̣t chương triǹ h viế t trên mô ̣t hê ̣ thố ng nề n (chẳ ng hạn Windows) có thể chạy trên nhiều hệ thống nền khác nhau (chẳ ng ha ̣n Linux, Unix…). + OOP có hiê ̣u quả cao . Thực tế cho thấ y các hê ̣ thố ng đươ ̣c xây dựng bằ ng OOP có hiê ̣u năng cao. 4
  12. 2. Mô ̣t số khái niêm ̣ cơ bản của lâ ̣p trin ̀ h hƣớng đố i tƣơ ̣ng 2.1 Kiể u dƣ̃ liêụ trƣ̀u tƣơ ̣ng ADT(Astract Data Type) Mô ̣t số người đinḥ nghiã OOP là lâ ̣p trình với các kiể u dữ liê ̣u trừu tươ ̣ng và các mố i quan hê ̣ giữa chúng . Trong phầ n này chúng ta sẽ xem xét các kiể u dữ liê ̣u trừu tươ ̣ng như là một khái niệm cơ bản của OOP và sử dụng một số ví dụ để minh họa. Đinh ̣ nghiã về kiể u dữ liê ̣u trừu tươ ̣ng : Mô ̣t kiể u dữ liê ̣u trừu tươ ̣ng là mô ̣t mô hiǹ h toán học của các đối tượng dữ liệu tạo thành một kiểu dữ liệu và các toán tử (phép toán) thao tác trên các đố i tươ ̣ng đó. Chú ý là trong định nghĩa này các toán tử thao tác trên các đố i tươ ̣ng dữ liê ̣u gắ n liề n với các đố i tươ ̣ng ta ̣o thành mô ̣t kiể u dữ liê ̣u trừu tươ ̣ng . Đặc tả về mô ̣t kiể u dữ liê ̣u trừu tươ ̣ng không có bấ t kỳ mô ̣t chi tiế t cu ̣ thể nào về cài đă ̣t bên trong của kiểu dữ liệu. Viê ̣c cài đă ̣t mô ̣t kiể u dữ liê ̣u trừu tươ ̣ng đòi hỏi mô ̣t quá triǹ h chuyể n đổ i từ đă ̣c tả của nó sang mô ̣t cài đă ̣t cu ̣ thể trên mô ̣t ngôn ngữ lâ ̣p triǹ h cu ̣ thể . Điề u này cho phép chúng ta phân biệt các ADT với các thuật ngữ kiểu dữ liệu (data type) và cấu trúc dữ liê ̣u (data structure). Thuâ ̣t ngữ kiể u dữ liê ̣u đề câ ̣p tới mô ̣t cài đă ̣t cu ̣ thể (có thể là kiểu built in hoă ̣c do người dùng đinh ̣ nghĩa) của một mô hình toán học được đặc tả bởi một ADT. Cấ u trúc dữ liê ̣u đề câ ̣p tới mô ̣t tâ ̣p các biế n có cùng kiể u đươ ̣c gắ n kế t với nhau theo mô ̣t cách thức xác đinh ̣ nào đó. Ví dụ về kiểu dữ liệu trừu tượng: Số nguyên. Kiể u dữ liê ̣u trừu tươ ̣ng số nguyên: ADT Integer: Dƣ̃ liêu: ̣ mô ̣t tâ ̣p các chữ số và mô ̣t dấ u tiề n tố là + hoă ̣c -. Chúng ta ký hiệu cả số là N. Các toán tử: constructor: khởi ta ̣o mô ̣t số nguyên sub(k): trả về hiệu N – k. add(k): trả về tổng N + k. …… End 2.2 Đối tƣợng (Objects) và lớp (Classes) Trong mô ̣t chương triǹ h hướng đố i tươ ̣ng chúng ta có các đố i tươ ̣ng . Các đối tượng này là đại diện cho các đối tượng thực trong thực tế . Có thể coi khá i niê ̣m đố i tươ ̣ng trong OOP chính là các kiể u dữ liê ̣u trong các ngôn ngữ lâ ̣p trình có cấ u trúc . Mỗi mô ̣t đố i tươ ̣ng có các dữ liệu riêng của nó và được gọi là các member variable hoặc là các data member . Các toán tử thao tác trên các dữ liệu này được gọi là các member function . Mỗi mô ̣t đố i tươ ̣ng là thể hiê ̣n (instance) của một lớp. Như vâ ̣y lớp là đa ̣i diê ̣n cho các đố i tươ ̣ng có các member function giố ng nhau và các data member cùng kiể u . Lớp là một sự trừu tượng hóa của khái niệm đối tượng. Tuy nhiên lớp không phải là mô ̣t ADT , nó là một cài đặt của một đă ̣c tả ADT. Các đối tượng của cùng một lớp có thể chia sẻ các dữ liệu dùng chung , dữ liê ̣u kiể u này được gọi là class variable. 5
  13. 2.3 Kế thƣ̀a (Inheritance) Khái niệm kế thừa này sinh từ nhu cầu sử dụng lại các thành phần phần mềm để phát triể n các phầ n mề m mới hoă ̣c mở rô ̣ng chức năng của phầ n mề m hiê ̣n ta ̣i . Kế thừa là mô ̣ t cơ chế cho phép các đố i tươ ̣ng của mô ̣t lớp có thể truy câ ̣p tới các member variable và function của mô ̣t lớp đã đươ ̣c xây dựng trước đó mà không cầ n xây dựng la ̣i các thành phầ n đó. Điề u này cho phép chúng ta có thể ta ̣o r a các lớp mới là mô ̣t mở rô ̣ng hoă ̣c cá biê ̣t hóa của một lớp sẵn có . Lớp mới (gọi là derived class ) kế thừa từ lớp cũ (gọi là lớp cơ sở base class). Các ngôn ngữ lập trình hướng đối tượng có thể hỗ trợ khái niệm đa kế thừa cho phép một lớp có thể kế thừa từ nhiều lớp cơ sở . Lớp kế thừa derived class có thể có thêm các data member mới hoặc các member function mới . Thêm vào đó lớp kế thừa có thể tiế n hành định nghĩa lại một hàm của lớp cơ sở và trong trường hơ ̣p này người ta nói rằ ng lớp kế thừa đã overload hàm thành viên của lớp cơ sở . 2.4 Dynamic Binding (ràng buộc động) và Porlymorphism (đa xa ̣ hoă ̣c đa thể ) Chúng ta lấy một ví dụ để minh hoạ cho hai k hái niệm này . Giả sử chúng ta có một lớp cơ sở là Shape , hai lớp kế thừa từ lớp Shape là Circle và Rectange . Lớp Shape là mô ̣t lớp trừu tươ ̣ng có mô ̣t member function trừu tươ ̣ng là draw (). Hai lớp Circle và Rectange thực hiê ̣n overload la ̣i hàm draw của lớp Shape với các chi tiế t cài đă ̣t khác nhau chẳ ng ha ̣n với lớp Circle hàm draw sẽ vẽ mô ̣t vòng tròn còn với lớp Rectange thì sẽ vẽ mô ̣t hiǹ h chữ nhâ ̣t. Và chúng ta có một đoạn chương trình chính hợp lệ như sau: int main() { Shape shape_list[4]; int choose; int i; for(i=0;i choose; if(choose==0) { shape_list[i] = new Circle(); }else{ shape_list[i] = new Rectange(); } } for(i=0;i
  14. shape_list[i]->draw(); } } Khi biên dich ̣ chương trình này thành mã thực hiê ̣n (file .exe) trình biên dịch không thể xác đinh ̣ đươ ̣c trong mảng shape _list thì phầ n tử nào là Circle phầ n tử nào là Rec tange và do đó không thể xác định được phiên bản nào của hàm draw sẽ được gọi thực hiện . Viê ̣c gọi tới phiên bản nào của hàm draw để thực hiện sẽ được quyết định tại thời điểm thực hiê ̣n chương triǹ h, sau khi đã biên dich ̣ và điều này được gọi là dynamic binding hoặc late binding. Ngươ ̣c la ̣i nế u viê ̣c xác đinh ̣ phiên bản nào sẽ đươ ̣c go ̣i thực hiê ̣n tương ứng với dữ liê ̣u gắ n với nó đươ ̣c quyế t đinh ̣ ngay trong khi biên dicḥ thì người ta go ̣i đó là static binding. Ví dụ này cũng cung cấp cho chúng ta một minh họa về khả năng đa thể (polymorphism). Khái niệm đa thể được dùng để chỉ khả năng của một thông điệp có thể đươ ̣c gửi tới cho các đố i tươ ̣ng của nhiề u lớp khác n hau ta ̣i thời điể m thực hiê ̣n chương trình. Chúng ta thấy rõ lời gọi tới hàm draw sẽ được gửi tới cho các đối tượng của hai lớp Circle và Rectange ta ̣i thời điể m chương trình đươ ̣c thực hiê ̣n . Ngoài các khái niệm cơ bản trên OOP còn có thêm mô ̣t số khái niê ̣m khác chẳ ng ha ̣n như name space và exception handling nhưng không phải là các khái niê ̣m bản chấ t . 3. Ngôn ngƣ̃ lâ ̣p trin ̀ h C++ và OOP. Giố ng như bấ t kỳ mô ̣t ngôn ngữ nào của con người , mô ̣t ngôn ngữ l ập trình là phương tiê ̣n để diễn tả các khái niê ̣m , ý tưởng. Viê ̣c phát triể n các chương trình hay phầ n mề m là quá triǹ h mô hiǹ h hóa các tra ̣ng thái tự nhiên của thế giới thực và xây dựng các chương triǹ h dựa trên các mô hình đó. Các chương trình thực hiện chức năng mô tả phương pháp cài đặt của mô hình. Các thế hệ ngôn ngữ lập trình : Có thể phân chia các thế hệ ngôn ngữ lập trình thành 4 thế hê ̣: 1: vào năm 1954 – 1958 (Fortran I) với đă ̣c điể m là các biể u thức toán ho ̣c 2: vào năm 1959 – 1961 (Fortran II, Cobol) với các thủ tu ̣c 3: vào những năm 1962 – 1970 (Pascal, Simula) với đă ̣c trưng là các khố i, các lớp… 4: đang phát triể n chưa có dẫn chứng thực tế . Các ngôn ngữ này ngày càng cách xa ngôn ngữ máy và các trình biên dịch của chúng ngày càng phải làm việc nhiều hơn. 3.1 Sƣ ̣ phát triể n của các ngôn ngƣ̃ lâ ̣p trin ̀ h hƣớng đố i tƣơ ̣ng 1967 Simula 1970 to 1983 Smalltalk 7
  15. 1979 Common LISP Object System 1980 Stroustrup starts on C++ 1981 Byte Smalltalk issue 1983 Objective C 1986 C++ 1987 Actor, Eiffel 1991 C++ release 3.0 1995 Java 1983 to 1989 Language books with OO concepts 1989 to 1992 Object-oriented design books 1992 to present Object-oriented methodology books Các ngôn ngữ lập trình khác Java Self Python Perl Prograph Modula 3 Oberon Smalltalk Venders ParcPlace, Digitalk, Quasar Prolog++ Ada 9X Object Pascal (Delphi) Object X, X = fortran, cobal, etc. C#. Như vâ ̣y là có rấ t nhiề u ngôn ngữ lâ ̣p trình hướng đố i tươ ̣ng đã ra đời và chiế m ưu thế trong số chúng là C ++ và Java. Mỗi ngôn ngữ đề u có đă ̣c điể m riêng của nó và thić h hơ ̣p với các liñ h vực khác nhau nhưng có lẽ C ++ là ngôn ngữ cài đă ̣t nhiề u đă ̣c điể m của OOP nhấ t. 3.2 Ngôn ngƣ̃ lâ ̣p trin ̀ h C++. C++ là một ngôn ngữ lập trình hướng đối tượng được Bjarne Stroustrup (AT & T Bell Lab ) (giải thưởng ACM Grace Murray Hopper năm 1994) phát triển từ ngôn ngữ C. C++ kế thừa cú pháp và mô ̣t số đă ̣c điể m ưu viê ̣t của C : ví dụ như xử lý con trỏ , thư viê ̣n các hàm phong phú đa dạng , tính khả chuyển cao , chương triǹ h cha ̣y nhanh … . Tuy nhiên về bản chấ t thì C++ khác hoàn toàn so với C, điề u này là do C++ là một ngôn ngữ lập trình hướng đố i tươ ̣ng. 4. Bài tập Bài tập 1: Download bộ công cụ DevCpp từ Internet và cài đặt trên máy tính của mình, viết chương trình đầu tiên, thực hiện biên dịch và chạy thử. Bài tập 2: Download bộ công cụ Visual Studio từ website của Microsoft và cài đặt trên máy tính của mình, viết chương trình, thực hiện biên dịch và chạy thử. 8
  16. CHƢƠNG II: NHƢ̃ NG KHÁI NIỆM MỞ ĐẦU 1. Chƣơng trin ̀ h đầ u tiên 1.1 Quá trình biên dich ̣ mô ̣t chƣơng trin ̀ h C++ Tấ t cả các ngôn ngữ trên máy tính đề u đươ ̣c dich ̣ từ mô ̣t da ̣ng nào đó mà con người có thể hiểu được một cách dễ dàng (các file mã nguồn được viết bằng một ngôn ngữ bậc cao) sang da ̣ng có th ể thực hiện được trên máy tính (các lệnh dưới dạng ngôn ngữ máy ). Các chương trình thực hiện quá trình này chia thành hai dạng được gọi tên là các trình thông dich ̣ (interpreter) và các trình biên dịch (compiler). Trình thông dịch: Mô ̣t triǹ h thông dich ̣ sẽ dich ̣ mã nguồ n thành các hành đô ̣ng (activity), các hành động này có thể bao gồm một nhóm các lệnh máy và tiến hành thực hiê ̣n ngay lâ ̣p tức các hành đô ̣ng này . Ví dụ như BASIC là một ngôn ng ữ điển hình cho các ngôn ngữ thông dich ̣ . BASIC cổ điể n thông dich ̣ từng dòng lê ̣nh thực hiê ̣n và sau đó quên ngay lâ ̣p tức dòng lê ̣nh vừa thông dich ̣ . Điề u này làm cho quá trình thực hiê ̣n cả mô ̣t chương triǹ h châ ̣m vì bô ̣ thông di c̣ h phải tiế n hành dich ̣ la ̣i các đoa ̣n mã trùng lă ̣p . BASIC ngày nay đã thêm vào qúa trình biên dịch để cải thiện tốc độ của chương trình . Các bộ thông dich ̣ hiê ̣n đa ̣i chẳ ng ha ̣n như Python , tiế n hành dich ̣ toàn bô ̣ chương trình qua mô ̣t ngôn ngữ trung gian sau đó thực hiê ̣n bằ ng mô ̣t bô ̣ thông dich ̣ nhanh hơn rấ t nhiề u . Các ngôn ngữ làm viê ̣c theo kiể u thông dich ̣ thươ ̀ ng có mô ̣t số ha ̣n chế nhấ t đi nh ̣ khi xây dự ng các dự án lớn (Có lẽ chỉ duy nhất Python là một ngoại lệ ). Bô ̣ thông dich ̣ cầ n phải luôn đươ ̣c lưu trong bô ̣ nhớ để thực hiê ̣n các mã chương triǹ h , và thậm chí ngay cả bộ thông dịch có tốc độ nhanh nhất cũng không thể cải thiện được hoàn toàn các hạn chế tốc độ .Hầu hế t các bô ̣ thông dich ̣ đề u yêu cầ u toàn bô ̣ mã nguồ n cầ n phải đươ ̣c thông dich ̣ mô ̣t lầ n duy nhấ t. Điề u này không những dẫn đế n các ha ̣n chế về kić h thước của chương triǹ h mà còn tạo ra các lỗi rất khó gỡ rối nếu như n gôn ngữ không cung cấ p các công cu ̣ hiê ̣u quả để xác đinḥ hiê ̣u ứng của các đoa ̣n mã khác nhau. Trình biên dịch : Mô ̣t triǹ h biên dich ̣ dicḥ mã nguồ n trực tiế p thành ngôn ngữ assembly hoă ̣c các lê ̣nh máy . Kế t quả cuố i cùng là mô ṭ file duy nhấ t hoă ̣c các file chứa các mã máy. Đây là mô ̣t quá trình phức ta ̣p và đòi hỏi mô ̣t vài bước . Quá trình chuyển đổi từ mã chương trình ban đầu thành mã thực hiện là tương đối dài đối với một trình biên dịch . Tùy thuộc vào sự nhạy cảm của người viết trình biên dịch , các chương trình sinh ra bởi mô ̣t triǹ h biên dich ̣ có xu hướng đòi hỏi it́ bô ̣ nhớ hơn khi thực hiê ̣n , và chúng chạy nhanh hơn rấ t nhiề u . Mă ̣c dù kić h thước và tố c đô ̣ thường là các lý do hàng đầ u cho viê ̣c sử du ̣ng mô ̣t trình biên dich ̣ , trong rấ t nhiề u trường hơ ̣p đây không phải là các lý do quan tro ̣ng nhấ t. Mô ̣t vài ngôn ngữ (chẳ ng ha ̣n như C ) đươ ̣c thiế t kế để các phầ n tách biê ̣t của mô ̣t chương triǹ h có thể đươ ̣c biên dich ̣ đô ̣c lâ ̣p hoàn toàn với nhau . Các phần này sau đó thậm chí có thể kết hợp thành một chương trình thực hiện cuối cùng duy nhất bởi một công cụ có tên là trình liên kết . Quá trình này gọi là separate compilation (biên dich ̣ đô ̣c lâ ̣p). Biên dịch độc lập có rất nhiều điểm lợi . Mô ̣t chương trình nế u dich ̣ ngay lâ ̣p tức toàn bô ̣ sẽ vươ ̣t quá các giới hạn của trình biên dịch hay môi trường biên dịch có thể được biên d ịch theo từng phầ n . Các chương trình có thể được xây dựng và kiểm thử từng phần một . Nế u mo ̣t phầ n nào đó đã làm viê ̣c đúng đắ n nó có thể đươ ̣c lưu la ̣i như là mô ̣t khố i đã hoàn thành . Tâ ̣p các phầ n đã làm viê ̣c và đươ ̣c kiể m thử có thể kế t hơ ̣p la ̣i với nhau ta ̣o thành các thư viê ̣n để các lâ ̣p trình viên khác có thể sử du ̣ng . Các đặc điểm này hỗ trợ cho việc tạo ra các chương trình lớn. Các đặc điểm gỡ lỗi của trình biên dịch đã cải t iế n mô ̣t cách đáng kể qua 9
  17. thời gian. Các trình biên dịch đầu tiên chỉ sinh ra mã máy , và lập trình viên phải chèn các câu lê ̣nh in vào để xem thực sự chương trình đang làm gì . Điề u này không phải lúc nào cũng hiệu quả. Các trình biên dịch hiện đại có thể chèn các thông tin về mã nguồn vào mã thực hiê ̣n của chương triǹ h . Thông tin này sẽ đươ ̣c sử du ̣ng bởi các bô ̣ gỡ lỗi cấ p đô ̣ nguồ n đầ y năng lực để chỉ ra chiń h xác điề u gì đang diễn ra tro ng mô ̣t chương triǹ h bằ ng cách theo dấ u (tracing) quá trình thực hiện của nó qua toàn bộ mã nguồn . Mô ̣t vài trình biên dịch giải quyết vấn đề tốc độ biên dịch bằng cách thực hiện quá trình biên dịch trong bộ nhớ (in-memory compilation). Các trình biên dịch theo kiểu này lưu trình biên dịch trong bô ̣ nhớ RAM . Đối với các chương trình nhỏ , quá trình này có thể xem như là một trình thông dich. ̣ Quá trình biên dịch Để lâ ̣p trình bằ ng C và C ++ chúng t a cầ n phải hiể u các bước và các công cu ̣ trong quá trình biên dịch . Mô ̣t vài ngôn ngữ (đă ̣c biê ̣t là C và C ++) bắ t đầ u thực hiê ̣n quá trình biên dich ̣ bằ ng cách cha ̣y mô ̣t bô ̣ tiề n xử lý đố i với mã nguồ n . Bô ̣ tiề n xử lý là m ột chương trình đơn giản thay thế các mẫu trong mã nguồn bằng các mẫu khác mà các lập trình viên đã đinh ̣ nghiã (sử du ̣ng các chỉ thi ̣tiề n xử lý : preprocessor directives). Các chỉ thị tiền xử lý được sử dụng để tiết kiệ m viê ̣c gõ các đoa ̣n chương trình thường xuyên sử du ̣ng và tăng khả năng dễ đọc cho mã nguồn . Tuy nhiên các chỉ thi tiề ̣ n xử lý này đôi khi cũng gây ra những lỗi rấ t tinh vi và khó phát hiê ̣n. Mã sinh ra bởi bộ tiền xử lý này thường đươ ̣c ghi lên mô ̣t file ta ̣m. Các trình biên dịch thường thực hiện công việc của nó theo hai pha . Đầu tiên là phân tích mã tiền xử lý. Bô ̣ biên dich ̣ chia mã tiề n xử lý thành các đơn vi ̣nhỏ và tổ chức chúng thành một cấ u trúc go ̣i là cây . Ví dụ như trong biểu thức : “A+B” các phầ n tử “A” , “+”, “B” sẽ đươ ̣c lưu trên nút của cây phân tić h . Mô ̣t bô ̣ tới ưu hóa toàn cu ̣c (global optimizer) đôi khi cũng đươ ̣c sử du ̣ng để ta ̣o ra mã chương triǹ h nhỏ hơn, nhanh hơn. Trong pha thứ hai , bô ̣ sinh mã duyê ̣t qua cây phân tích và sinh ra hoă ̣c là mã assemble hoă ̣c mã máy cho các nút của cây . Nế u như bô ̣ sinh mã ta ̣o ra mã assembly , thì sau đó chương triǹ h dich ̣ mã assembler sẽ thực hiê ̣n côn g viê ̣c tiế p theo . Kế t quả của hai trường hơ ̣p trên đề u là mô ̣t module object (mô ̣t file thường có đuôi là .o hoă ̣c .obj). Sau đó mô ̣t bô ̣ tố i ưu hoá nhỏ (peep-hole) sẽ được sử dụng để loại bỏ các đoạn chứa các câu lệnh assembly thừa. Viê ̣c sử du ̣ng từ “object” để mô tả các đoa ̣n mã máy là mô ̣t thực tế không đúng lắ m. Từ này đã đươ ̣c dùng trước cả khi lâ ̣p triǹ h hướng đố i tươ ̣ng ra đời . Từ “object” đươ ̣c sử du ̣ng có ý nghiã như là từ “goal” khi nói về viê ̣c biên dich, ̣ trong khi đó trong lâ ̣p trình hướng đối tượng nó lại có nghĩa là “a thing with boundaries” . Trình liên kết kết hợp mô ̣t danh sách các module object thành mô ̣t chương trình thực hiê ̣n có thể na ̣p vào bô ̣ nhớ và th ực hiện bởi hệ điều hành . Khi mô ̣t hàm trong mô ̣t module object ta ̣o ra mô ̣t tham chiế u tới mô ̣t hàm hoă ̣c mô ̣t biế n trong mô ̣t module object khác , trình liên kết sẽ sắp xếp lại các tham chiếu này ; điề u này đảm bảo rằ ng tấ t cả c ác hàm và dữ liệu external được sử dụng trong quá trình biên dịch là đều tồn tại . Trình liên kết cũng thêm vào các module object đă ̣c biê ̣t để thực hiê ̣n các hành đô ̣ng khởi đô ̣ng . Trình liên kết có thể tìm kiếm trên các file đă ̣c biê ̣t go ̣i là các thư viê ̣n để sắ p xế p la ̣i tấ t cả các tham chiế u tới chúng . Mỗi thư viê ̣n chứa mô ̣t tâ ̣p các module object trong mô ̣t file. Mô ̣t thư viê ̣n đươ ̣c ta ̣o ra và bảo trì bởi mô ̣t lâ ̣p triǹ h viên có tên là librarian. Kiể m tra kiể u tinh ̃ 10
  18. Trình biên dịch thực hiện kiểm tra kiểu trong pha đầu tiên của quá trình biên dịch . Quá trình kiểm tra này thực hiện kiểm thử việc sử dụng các tham số của các hàm và ngăn chă ̣n rấ t nhiề u lỗi lâ ̣p trình k hác nhau. Vì quá trình kiểm tra kiểu được thực hiện trong qúa trình biên dịch chứ không phải trong quá trình chương trình thực hiện nên nó được gọi là kiể m tra kiể u tiñ h. Mô ̣t vài ngôn ngữ lâ ̣p triǹ h hướng đố i tươ ̣ng (Java chẳng hạn) thực hiê ̣n kiể m tra kiể u ta ̣i thời điể m chương trình cha ̣y (dynamic type checking). Nế u kế t hơ ̣p cả viê ̣c kiể m tra kiể u tiñ h và đô ̣ng thì sẽ hiê ̣u quả hơn nhưng kiể m tra kiể u đô ̣ng cũng làm cho chương trình thực hiê ̣n bi ̣ả nh hưởng đôi chút . C++ sử du ̣ng kiể m tra kiể u tiñ h . Kiể m tra kiể u tiñ h báo cho lâ ̣p triǹ h viên về các lỗi về sử du ̣ng sai kiể u dữ liê ̣u trong quá triǹ h biên dịch, và do đó tối ưu hóa tốc độ thực hiện chương trình . Khi ho ̣c C++ chúng ta sẽ thấy hầu hế t các quyế t đinḥ thiế t kế của ngôn ngữ đề u tâ ̣p trung vào củng cố các đă ̣c điể m : tố c đô ̣ nhanh, hướng đố i tươ ̣ng, các đặc điểm mà đã làm cho ngôn ngữ C trở nên nổi tiếng . Chúng ta có thể không dùn g tùy cho ̣n kiể m tra kiể u tiñ h của C ++ hoă ̣c cũng có thể thực hiê ̣n viê ̣c kiể m tra kiể u đô ̣ng - chỉ cần viết thêm mã. Các công cụ cho việc biên dịch độc lập Viê ̣c biên dich ̣ đô ̣c lâ ̣p rấ t cầ n thiế t nhấ t là đố i với các dự án lớn. Trong ngôn ngữ C và C ++, mô ̣t lâ ̣p trình viên có thể ta ̣o ra các đoa ̣n chương trình nhỏ dễ quản lý và đươ ̣c kiể m thử đô ̣c lâ ̣p . Công cu ̣ cơ bản để chia mô ̣t chương triǹ h thành các phầ n nhỏ là khả năng ta ̣o ra các thay thế đươ ̣ c đă ̣t tên hay là các chương triǹ h con . Trong C và C ++ mô ̣t chương triǹ h con đươ ̣c go ̣i là mô ̣t hàm , và các hàm là các đoạn mã có thể được thay thế trong các file khác nhau , cho phép thực hiê ̣n quá trình biên dich ̣ đô ̣c lâ ̣p . Nói mô ̣t cách khác các hàm là các đơn vị nguyên tử của mã nguồn , vì chúng ta không thể đặt các phần khác nhau của hàm trong các file khác nhau nên nội dung của một hàm cần phải được đặt hoàn toàn trong một file (mă ̣c dù các file có thể chứa nhiề u hơn 1 hàm). Khi chúng ta go ̣i đế n mô ̣t hàm , chúng ta thường truyền cho nó một vài tham số , đó là các giá trị mà chúng ta muốn hàm làm việc với khi nó thực hiện . Khi hàm thực hiê ̣n xong chúng ta thường nhâ ̣n đươ ̣c mô ̣t giá tri ̣trả về , mô ̣t giá tri ̣mà hàm trả la ̣i như là mô ̣t kế t quả . Cũng có thể viết các hàm không nhận các tham số và không trả về bất kỳ giá trị nào . Để tạo ra một chương trình với nhiều file , các hàm trong mô ̣t file phải truy câ ̣p tới các hàm và dữ liê ̣u trong các file khác . Khi biên dicḥ mô ̣t file , trình biên dịch C hoặc C ++ phải biết về các hàm và dữ liệu trong các file khác đặc biệt là tên và cách dùng chúng . Trình biên dịch đảm bảo các hàm và dữ liê ̣u đươ ̣c sử du ̣ng đúng đắ n . Qúa trình báo cho trình biên dịch tên và nguyên mẫu của các hàm và dữ liệu bên ngoài được gọi là khai báo (declaration). Khi chúng ta đã khai báo một hàm hoặc biế n trình biên dich ̣ sẽ biế t cách thức kiể m tra để đảm bảo các hàm và dữ liệu này được sử dụng đúng đắn. Including các file Header Hầ u hế t các thư viê ̣n đề u chứa mô ̣t số lươ ̣ng đáng kể các hàm và biế n . Để tiế t kiê ̣m công sứ c và đảm bảo sự nhấ t quán khi khai báo ngoài các phầ n tử này , C và C ++ đã sử dụng một loại file được gọi là file header . Mỗi file header là mô ̣t file chứa các khai báo ngoài cho 1 thư viê ̣n; theo qui ước các file này có phầ n mở rô ̣ng là .h, nhưng chúng ta cũng có thể dùng các đuôi file khác cho chúng chẳng hạn như .hpp hoă ̣c .hxx. Lâ ̣p triǹ h viên ta ̣o ra các file thư viê ̣n sẽ cung cấ p các header file . Để khai báo các hàm và các biế n bên ngoài thư viê ̣n người dùng đơn giản chỉ cầ n thực hiê ̣n include file header đó . Để include mô ̣t file header chúng ta sử du ̣ng chỉ thi ̣tiề n xử lý #include. Chỉ thị này sẽ báo cho bộ xử lý mở file 11
  19. header có tên tương ứng và chèn nô ̣i dung của file đó vào chỗ mà chỉ thi ̣ #include đươ ̣c sử dụng. Tên file sử du ̣ng sau chỉ thi ̣ #include có thể nằ m giữa hai dấ u < và > hoă ̣c giữa hai dấ u “. Ví dụ: #include Nế u chúng ta sử du ̣ng chỉ thi ̣include theo cách trên thì b ộ tiền xử lý sẽ tìm file header theo cách đă ̣c thù đố i với cài đă ̣t của chúng ta , nhưng thường thì sẽ có mô ̣t vài đường dẫn mà chúng ta chỉ đinh ̣ cu ̣ thể trong biế n môi trường của trình biên dich ̣ hoă ̣c trên dòng lệnh để sử dụng cho việc tìm các file header . Cơ chế thiế t lâ ̣p các đường dẫn này phu ̣ thuô ̣c vào triǹ h biên dich ̣ và môi trường mà chúng ta làm viê ̣c. Ví dụ: #include “header.h” Chỉ thị tiền xử lý như trên thường có ý nghĩa là báo cho bô ̣ tiề n xử lý tìm file tương ứng trong thư mục hiện tại trước nếu không thấy thì sẽ tìm giống như trong trường hợp tên file include đươ ̣c đă ̣t giữa hai dấ u < và >. Nói chung thì đối với các file include chuẩn hoặc đươ ̣c sử du ̣ng nhiề u chúng ta nên đă ̣c nó trong thư mu ̣c mă ̣c đinh ̣ là include dưới thư mu ̣c cài đặt trình biên dịch và dùng chỉ thị theo kiểu , còn đối với các file đặc thù với ứng dụng cụ thể thì dùng kiểu tên file đặt giữa hai dấu “” . Trong quá trình phát triể n của C ++ các nhà cung cấp các trình biên dịch có các qui ước đặt tên khác nhau và các hệ điều hành lại có các hạn chế tên khác nhau đặc biệt là độ dài của tên file . Các vấn đề này gây ra các vấ n đề về tiń h khả chuyể n của chương triǹ h . Để khắ c phu ̣c vấ n đề này người ta đã sử du ̣ng mô ̣t đinḥ da ̣ng chuẩ n cho phép các tên file header có thể dài hơn 8 ký tự và bỏ đi phần tên mở rô ̣ng. Để phân biê ̣t mô ̣t chương trình C và C ++ đôi khi người ta còn dùng cách thêm mô ̣t ký tự “c” vào trước tên của các file header , chi tiế t này cũng đươ ̣c chấ p nhâ ̣n đố i với C và C++. Quá trình liên kết Trình liên kết tập hợp các module object (thường là các file có phần mở rộng là .o hoă ̣c .obj), đươ ̣c sinh ra bởi trình biên dich ̣ , thành một chương trình có thể thực hiện được và hệ điều hành có thể nạp vào bộ nhớ và chạy . Đây là pha cuố i cùng trong quá trình biên dịch. Các đặc đ iể m của các triǹ h liên kế t thay đổ i phu ̣ thuô ̣c vào các hê ̣ thố ng khác nhau . Nói chung chúng ta chỉ cần chỉ rõ cho trình liên kết biết tên của các module object và các thư viê ̣n mà chúng ta muố n liên kế t , và tên của chương trì nh khả cha ̣y cuố i cùng . Mô ̣t vài hê ̣ thố ng đòi hỏi chúng ta cầ n phải tự go ̣i tới các trình liên kế t . Tuy nhiên hầ u hế t các trình biên dich ̣ hoàn chỉnh đề u thực hiê ̣n hô ̣ chúng ta công viê ̣c này . Sƣ̉ du ̣ng các thƣ viêṇ Giờ đây ch úng ta đã biết các thuật ngữ cơ bản , chúng ta có thể hiểu cách thức sử dụng một thư viện. Để sử du ̣ng mô ̣t thư viê ̣n cầ n phải : + Include file header của thư viê ̣n + Sử du ̣ng các hàm và các biế n trong thư viê ̣n + Liên kế t thư viện vào chương trình khả chạy cuối cùng Các bước này cũng đúng với các module object không có trong các thư viện . Including mô ̣t file header và liên kế t các module object là các bước cơ bản để thực hiê ̣n viê ̣c biên dich ̣ đô ̣c lâ ̣p trong C và C++. 12
  20. Trình liên kết làm thế nào để tìm một file thƣ viện Khi chúng ta ta ̣o ra mô ̣t tham chiế u ngoài tới mô ̣t hàm số hoă ̣c mô ̣t biế n số trong C hoă ̣c C++, trình liên kết , khi bắ t gă ̣p tham chiế u này , có thể thực hiện mộ t trong hai viê ̣c sau: nế u nó chưa thấ y phầ n đinḥ nghiã của hàm hay biế n này , nó sẽ thêm định danh vào danh sách các tham chiế u chưa đươ ̣c đinh ̣ nghiã của nó . Nế u như trình liên kế t đã bắ t gă ̣p đinh ̣ nghiã của tham chiế u đó , tham chiế u sẽ đươ ̣c sắ p xế p la ̣i . Nế u như triǹ h liên kế t không tim ̀ thấ y đinh ̣ nghiã của tham chiế u trong danh sách các module object nó sẽ tiế n hành tìm kiếm trong các thư viện . Các thư viện có một vài loại chỉ số nên trình li ên kế t không cầ n thiế t phải tìm kiế m hế t trong các module objetc của thư viê ̣n – nó chỉ cần xem xét các phần chỉ mục . Khi trình liên kế t tìm thấ y mô ̣t đinḥ nghiã trong mô ̣t thư viê ̣n , toàn bô ̣ module object chứ không chỉ phầ n đi ̣ nh nghiã của hàm , sẽ được liên kết vào chương trình thực hiện. Chú ý rằng toàn bộ thư viện sẽ không được liên kết , chỉ có phần định nghĩa mà chương trình tham chiếu tới . Như vâ ̣y nế u chúng ta muố n tố i ưu về kić h thước củ a chương trình chúng ta có thể cho mỗi hàm vào mô ̣t file khi xây dựng các thư viê ̣n riêng của mình. Điề u này đòi hỏi công sức edit nhiề u hơn nhưng cũng có thể có ích . Vì trình liên kết tìm kiếm các file theo thứ tự chúng ta c ó thể che đi sự tồn tại của một hàm thư viện bằng cách dùng hàm của chúng ta với phần định nghĩa và prototype y hệt như hàm thư viện . Tuy nhiên điề u này cũng có thế gây ra các lỗi mà chúng ta không thể kiể m soát đươ ̣c . Khi mô ̣t chương triǹ h khả cha ̣y đươ ̣c viế t bằ ng C hoă ̣c C ++ đươ ̣c ta ̣o ra , mô ̣t số các thành phần nhất định sẽ được liên kết với nó một cách bí mật . Mô ̣t trong các thành phầ n này chính là module khởi động (startup), module này chứ a các thủ tu ̣c khởi ta ̣o cầ n phải đươ ̣c thực hiê ̣n bấ t cứ khi nào mô ̣t chương trình C hay C ++ bắ t đầ u cha ̣y. Các thủ tục này thiế t lâ ̣p stack và các biế n khởi ta ̣o nhấ t đinh ̣ trong chương triǹ h. Trình biên dịch luôn thực hiện vi ệc tìm kiếm trong các thư viện chuẩn để thực hiện liên kế t các hàm chuẩ n mà chúng ta dùng trong chương trình nên để dùng các hàm trong các thư viện chuẩn chúng ta đơn giản chỉ cần include file header của thư viện đó . Còn đối với các thư viê ̣n riêng do chúng ta ta ̣o ra chúng ta cầ n chỉ rõ tên thư viê ̣n cho triǹ h liên kế t (chẳ ng ha ̣n thư viê ̣n graphics không phải là mô ̣t thư viê ̣n chuẩ n ). 1.2 Chƣơng trin ̀ h đầ u tiên. Cách tốt nhất để học lập trình là xem các chương trình của người khác viết và học tập các kỹ thuật lập trình của họ . Sau đây là chương triǹ h HelloWorld đươ ̣c viế t bằ ng C ++, mô ̣t chương triǹ h mà hầ u hế t các sách lâ ̣p triǹ h đề u lấ y làm ví du ̣ mở đầ u . // Chương trình HelloWorld // File hello.cpp // In ra màn hiǹ h xâu “Hello, World!” #include // Khai báo luồ ng cout để sử du ̣ng int main() { cout
nguon tai.lieu . vn