🔙 Quay lại trang tải sách pdf ebook Giáo trình kỹ thuật lập trình hướng đối tượng Ebooks Nhóm Zalo [ RƯỜNG ĐẠI HỌC HỪNG VƯƠNG TS. PHẠM THẾ QUẾ (CHỦ BIÊN) - ThS. ĐINH THÁI SƠN ThS. NGUYỄN ĐÌNH NHƯ - ThS. vũ THỊ THU MINH - ThS. NÔNG THỊ LÝ GIÁO TRÌNH u W lặ p trìn h 1 " a BDỊTnPđói tư ợ n g Sách tặng NGUYỄN Ọ C L i ệ u NHÀ XUẤT BẢN ĐẠI HỌC THÁI NGUYÊN TRƯỜNG ĐẠI HỌC HÙNG VƯƠNG TS. Phạm Thế Quế (Chủ biên) - ThS. Đinh Thái Son ThS. Nguyễn Đình Nhu' - ThS. Vũ Thị Thu Minh - ThS. Nông Thị Lý (G iá o TRÌNH KỸ THUẬT LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG NHÀ XUÁT BẢN ĐẠI HỌC THÁI NGUYÊN NĂM 2017 02-49 ĐH TN -2017 LỜI MỞ ĐÀU Lập trinh cấu trúc là phương pháp tổ chức, phân chia chương trinh thành các hàm, thủ tục, chúng được dùng để xừ lý dữ liệu nhưng lại tách rời các cấu trúc dữ liệu. Thông qua các ngôn ngữ Foxpro, Pascal, c đa số những ngươi làm Tin học đã khá quen biết với phương pháp lập trình này. Lập trình hướng đối tượng dựa trên việc tổ chức chương trinh thành các lớp. Khác với hàm và thủ tục, lớp là một đơn vị bao gồm cà dữ liệu và phương thức xử lý. Vì vậy lớp có thể mô tả các thực thể một cách chân thực, đầy đủ cả phẩn dữ liệu và yêu cầu quản lý. Tư tường lập trinh hướng đối tượng được áp dựng cho hầu hết các ngôn ngữ chạy trên môi trường Windows và Unix như Visual C++, Visual c#, PHP, Java. Ngôn ngữ lập trình c ra đời năm 1973 với mục đích ban đầu là để viết hệ điều hành Unix trên máy tính mini PDP. Sau đó c đã được sừ dụng rộng rãi trên nhiều loại máy tính khác nhau và đã trờ thành một ngôn ngữ lập trình cấu trúc rất được ưa chuộng. Để đưa ngôn ngũ c vào thế giới hướng đối tượng, năm 1980 nhà khoa học người Mỹ B.Stroustrup đã cho ra đời một ngôn ngữ c mới có tên ban đầu là “C có lớp”, sau đó đen năm 1983 thì gọi là c++. Ngôn ngữ c++ là một sự phát triển mạnh mẽ của c. Trong c++ chẳng những đưa vào tất cả các khái niệm, công cụ của lập trình hướng đôi tượng mà còn đưa vào nhiêu khả năng mới mẻ cho hàm. Như vậy c++ là một ngôn ngữ lai cho phép tổ chức chương trinh theo các lớp và các hàm. Có thể nói c++ đã thúc đẩy ngôn ngữ c vốn đã rất thuyết phục đi vào thế giới lập trình hướng đối tượng và c++ đã trở thành ngôn ngữ hướng đối tượng nổi bật trong những năm 90. Trong những năm gần đây, lập trinh hướng đối tượng đã trỡ nên gần gũi nhờ sự ra đời liên tiếp của các ngôn ngữ lập trình hướng đổi tuợng. Sức mạnh của phương pháp lập trình hướng đối tượng thể hiện ờ chỗ khả năng mô hỉnh hóa hệ thống dựa trên các đối tuợng thực tế, khả năng đóng gói và bảo vệ an 3 toàn dữ liệu, khả nâng sử dụng lại mã nguồn để tiếp cận chi phí và tài nguyên, đặc biệt là khả nâng chia sẻ mã nguồn trong cộng đồng lập trình viên chuyên nghiệp. Những điểm mạnh này hứa hẹn sẽ thúc đẩy phát triển môi trường lập trình tiên tiến cùng với nền công nghiệp lap ráp phần mềm với các thư viện thành phần có sẵn. Giáo trình Kỹ thuật lập trình hướng đói tượng được biên soạn phục vụ môn học Lập trình hướng đối tượng (3 tín chỉ), dành cho đối tượng là sinh viên năm thứ 2 và năm thứ 3 của trường. Nhóm tác giả hi vọng rằng giáo trình sẽ cung cấp một cách tiếp cận tổng thể về phương pháp lập trình hướng đối tượng đồng thời cũng cung cấp các kỹ thuật cơ bản về phát triển các ứng dụng bằng ngôn ngữ lập trinh C++, một ngôn ngữ lập trình hướng đối tượng được sử dụng thông dụng nhất hiện nay. Giáo trinh này là kết quả tổng hợp các kiến thức và kinh nghiệm giảng dạy nhiều năm của các thầy cô tại trường Đại học Hùng Vương về lập trình hướng đối tượng. Mặc dù rất cố gắng, song chắc chắn giáo trình không thể tránh khỏi những thiếu sót, nhóm tác giả rất mong nhận được những ý kiến đóng góp, trao đổi của các nhà khoa học, đồng nghiệp và các độc giả để cuốn sách ngày càng được hoàn thiện hơn. Mọi góp ý xin gửi về: Bộ môn Công nghệ phần mềm - Khoa Kỹ thuật công nghệ - Trường Đại học Hùng Vưcmg. Xin trân Ưọng cảm ơn ỉ CÁC TÁC GIẢ 4 MỤC LỤC CHƯƠNG 1. CÁC KHÁI NIỆM c ơ SỞ CỦA LẬP TRÌNH HƯỚNG ĐÓI TƯỢNG ........................................................................................................9 1 1. Giới thiệu........................................................................................................ 10 1.1.1. Tiếp cận hướng đối tượng............................................................... 10 1.1.2. Những nhược điểm của lập trinh hướng thu tụ c ..............................10 1.1.3. Đặc điểm lập trinh hướng đối tượng..................................................11 1.2. Các khái niệm cơ bản của lập trình hướng đối tượng ............................... 12 1.2.1. Đối tượng........................................................................................ 12 1.2.2. Lớp................................................................................................... 12 1.2.3. Trừu tượng hóa dữ liệu và bao gói thông tin ................................ 13 1.2.4. Kế thừa............................................................................................ 14 1.2.5. Tương ứng bội ...................................................................................15 1.2.6. I.iên kết động.................................................................................. 16 1.2.7. Truyền thông báo............................................................................ 16 1.3. Các bước cần thiết để thiết kế chương trinh theo hướng đối tượng............... 17 1.4. Các ưu điểm của lập trình hướng đối tượng................................................. 17 1.5. Các ngôn ngữ hướng đối tượng..................................................................... 18 1.6. Một số ứng dụng cua LTHĐT.......................................................................20 CHƯƠNG 2. CÁC MỜ RỘNG CỦA NGÔN NGỮ C++ 21 2.1. Giới thiệu chung về C++................................................................................21 2.2. Một số mờ rộng của C++ so với c ................................................................22 2.2.1. Đặt lời chu thích..................................................................................22 2.2.2. Khai báo biến..................................................................................... 22 2.2.3. Phép chuyển kiểu bắt buộc................................................................23 2.2.4. Lấy địa chỉ các phần tử mảng thực 2 chiều..................................... 24 2.3. Vào ra trong c — ............................................................................................26 2.3.1. Xuất dữ liêu ..........................................................................................26 2.3.2. Nhập dữ liệu .........................................................................................26 2.3.3. Định dạng khi in ra màn hình ........................................................... 27 2.4. Cấp phát và giải phóng bộ nhớ........................................................................ 31 2.4.1. Toán từ new để cấp phát bộ nhớ.......................................................... 31 2.4.2. Toán tử delete.......................................................................................32 2.5. Biển tham chiếu................................................................................................ 34 2.6. Hăng tham chiếu............................................................................................... 35 2.7. Truyền tham số cho hàm theo tham chiếu......................................................36 2.8. Hàm trả về giá trị tham chiếu.......................................................................... 43 2.9. Hàm với tham số có giá trị mặc định............................................................45 2.10. Các hàm nội tuyến (inline)............................................................................ 47 2.11. Hàm tái bội...................................................................................................... 51 CHƯƠNG 3. L Ớ P..................................................................................................58 3 1. Định nghĩa lớp...................................................................................................59 3 2. Tao lập đối tượng............................................................................................. 60 3.3. Truy nhập tới các thành phần của lớ p ......................................................... 61 3 4 Con trò đối tượng...........................................................................................69 3.5. Con Ưỏ this.....................................................................................................71 3 .6. Hàm b ạn ..........................................................................................................73 3.7. Dữ liệu thành phần tĩnh và hàm thánh phần tĩn h ........................................ 80 3.7.1. Dữ liệu thành phần tĩn h .................................................................... 80 3.7.2. Hàm thành phẩn tĩnh..........................................................................83 3.8. Hàm tao (constructor).................................................................................... 86 3.9. Hàm tạo sao chép...........................................................................................95 3.9.1. Hàm tạo sao chép mặc định.............................................................. 95 3.9.2. Hàm tạo sao chép.............................................................................. 98 3.10. Hàm hủy (destructor)................................................................................ 105 CHƯƠNG 4. TOÁN TỬ TẢI BỘI 111 4.1. Định nghĩa toán tử tải bội.......................................................................... 111 6 4.2. Một số lưu ý khi xây dựng toán tử tải bội............................................... 112 4.3. Một số vi dụ..................................................................................................112 4.4. Định nghĩa chồng các toán tử ++ , - - ......................................................124 4.5. Định nghĩa chồng toán tử « và » ........................................................ 128 CHƯƠNG 5. KÉ THỪA 131 5.1. Giởi thiệu....................................................................................................131 5.2. Đơn kế thừa................................................................................................ 132 5.2.1. Định nghĩa lơp dẫn xuất từ một lớp cơ sờ .................................. 132 5.2.2. Truy nhập các thành phần trong lớp dẫn xuất............................ 133 5.2.3. Định nghĩa lại các hàm thành phẩn của lớp cơ sờ trong lớp dẫn xuất.................................................................................................... 134 5.2.4. Hàm tạo đối với tính kế thưa.......................................................... 140 5.2.5. Hàm hủy đối với tính kế thừa...................................................... 143 5.2.6. Khai báo protected........................................................................ 144 5.2.7. Dần xuất protected........................................................................ 145 5.3. Da kể thừa................................................................................................... 145 5.3.1. Định nghĩa lóp dẫn xuất tò nhiều lớp cơ sờ................................ 145 5.3.2. Một số ví dụ về đa kể thừa........................................................... 146 5.4. Hàm à o ...................................................................................................... 155 5.4.1 Đặt vấn đề...................................................................................... 155 5.4.2. Định nghĩa hàm áo..........................................................................158 5.4.3. Quy tấc gọi hàm áo.........................................................................161 5.4.4. Quy tắc gán địa chi đối tượng cho con trỏ lớp cơ sờ.......................161 5.5. Lớp cơ sờ ả o ............................................................................................. 166 5.5.1. Khai báo lớp cơ sờ ảo .................................................................. 166 5.5.2. Hàm tạo và hàm hủy đối với lớp cơ sờ ảo .................................. 169 CHƯƠNG 6. KHUÔN HÌNH 177 6.1. Khuôn hình hàm....................................................................................... 177 6.1.1. Khái niệm...................................................................................... 177 6.1.2. Tạo một khuôn hình hàm............................................................. 177 6.1.3. Sử dụng khuôn hình hàm............................................................. 179 6.1.4. Các tham số kiểu của khuôn hinh hàm ......................................... 179 6.1.5. Định nghĩa chồng các khuôn hình h àm ........................................ 182 6.2. Khuôn hình lớp............................................................................................. 183 6.2.1. Khái niệm......................................................................................... 183 6.2.2. Tạo một khuôn hình lớp.................................................................. 184 6.2.3. Sử dung khuôn hinh lớp.................................................................. 185 6 2 4. Các tham số trong khuôn hình lớp................................................ 186 6 2 5 Tom tãt............................................................................................. 187 PHỤ LỤC 1. CÁC DÒNG XUÁT NHẬP 189 1.1. Các lớp stream............................................................................................. 189 1.2. Dòng cin và toán tử nhập » ...................................................................... 190 1 2 1 Dỏng cin............................................................................................ 190 1.2.2. Toán tử trích » .............................................................................. 190 1.3. Nhập ký tự và chuỗi ký tự .......................................................................... 190 1.3.1. Phương thức get() có 3 dạng:........................................................ 190 1.3.2. Phương thức getline()..................................................................... 192 1.3.3. Phương thức ignore......................................................................... 193 1.4. Dòng cout và toán tử xuất« ..................................................................... 193 1.4.1. Dòng cout......................................................................................... 193 1.4.2. Toán tử xuất« .............................................................................. 193 1.4.3. Các phương thức định dạng........................................................... 193 1.4.4. Cờ định dạng.................................................................................... 195 1.4.5. Các phương thức bật tắt cờ ............................................................ 200 1 4 6. Các bộ phận định dang................................................................... 200 1.4.7. Các hàm định dạng......................................................................... 201 1.5. Các dòng chuẩn........................................................................................... 203 1.6. Xuất ra máy in ............................................................................................. 204 PHỤ LỤC 2. THỨ T ự Ưu TIÊN CỦA CÁC PHÉP TOÁN 207 TÀI LIỆU THAM KHẢO 211 Chương I C Á C K H Á I N IỆ M C ơ S Ở C Ử A L Ậ P T R Ì N H H Ư Ớ N G D ố i T Ư Ợ N G Chương 1 trình bày những vấn để sau: r Thao luận vê cách tiếp cận hướng đối tượng, những nhược điêm cua lập trinh truyến thong và các đặc điẻm cua lập trinh hướng đối tượng. > Các khái niệm cơ sơ cua phương pháp hưởng đối lượng: • Đoi tượng • Lớp • Trừu lượng hóa dữ liệu và bao gói thông tin • Kế thừa • Tương ứng bội • Liên kết động • Truyẽn thông báo > Các bước cần thiết đế thiết kế chương trình theo hướng đổi tượng > Các ưu điẽm cùa ìập trình hướng đổi tượng > Các ngôn ngữ hướng đối tượng > Một số ứng dụng cùa lập trình hướng đối tượng 9 1.1. Giói thiệu 1.1.1. Tiếp cận hướng đổi tượng Trong thế giói thực, xung quanh chúng ta là những đối tượng, đó là các thực thể có mối quan hệ với nhau. Ví dụ các phòng trong một công ty kinh doanh được xem như những đối tượng. Các phòng ở đây có thể là: phòng quản lý, phòng bán hàng, phòng kế toán, phòng tiếp thị,... Mỗi phòng ngoài những cán bộ đàm nhiệm những công việc cụ thề, còn có những dữ liệu riêng như thông tin về nhân viên, doanh số bán hàng, hoặc các dừ liệu khác có liên quan đến bộ phận đó. Việc phân chia các phòng chức năng trong công ty sẽ tạo điều kiện dễ dàng cho việc quản lý các hoạt động. Mỗi nhân viên trong phòng sê điều khiển và xử lý dữ liệu của phòng đó. Ví dụ phòng kế toán phụ trách về lương bổng nhân viên trong công ty. Nếu bạn đang ở bộ phận tiếp thị và cần tìm thông tin chi tiết về lương của đơn vị minh thi sẽ gửi yêu cầu về phòng kế toán. Với cách làm này bạn được đảm bảo là chi có nhân viên của bộ phận kế toán được quyền truy cập dữ liệu và cung cấp thông tín cho bạn. Điều này cũng cho thấy rằng, không có người nào thuộc bộ phận khác có thể truy cập và thay đổi dữ liệu của bộ phận kế toán. Khái niệm như thế về đối tượng hầu như có thể được mở rộng đối với mọi lĩnh vực trong đời sống xã hội và hơn nữa - đối với việc tổ chức chương trình. Mọi ứng dụng có the được định nghĩa như một tập các thực thể - hoặc các đối tượng, sao cho quá trình tái tạo những suy nghĩ của chúng ta là gần sát nhất về thế giới thực. 1.1.2. Những nhược điểm cùa lập ừ ình hướng thù tục Cách tiếp cận lập trinh truyền thống là lập trinh hướng thủ tục (LTHTT). Theo cách tiếp cận này thi một hệ thống phần mềm được xem như là dãy các công việc cần thực hiện như đọc dữ liệu, tính toán, xử lý, lập báo cáo và in ấn kết quả V.V.. Mỗi công việc đó sẽ được thực hiện bời một số hàm nhất định. Như vậy trọng tâm của cách tiếp cận này là các hàm chức nàng. LTHTT sử dụng kỹ thuật phân rã hàm chức năng theo cách tiếp cận trên xuống (top-down) để tạo ra cấu trúc phân cấp. Các ngôn ngữ lập trình bậc cao như COBOL, FORTRAN, PASCAL, c , V.V ., là những ngôn ngữ lập trình hướng thủ tục. Những nhược điểm chính của LTHTT là: > Chương trinh khó kiểm soát và khó khăn trong việc bổ sung, nâng cấp chương trình. Chương trình được xây dựng theo cách tiếp cận hướng thủ tục thực chất là danh sách các câu lệnh mà theo đó máy tính cần thực hiện. Danh sách các lệnh đó được tổ chức thành từng nhóm theo đơn vị cấu trúc của ngôn ngừ lập trinh và được gọi là hàm/thủ tục. Trong chương trinh có nhiều hàm/thủ tục, thường thi có nhiều thành phần dữ liệu quan trọng sẽ được khai báo tổng thể (global) để các hàm/thủ tục có thể truy nhập, đọc và làm thay đổi giá trị của biến tổng thể. Điều này sẽ làm cho chương trình rất khó kiểm soát, nhất là đối với các chương trình lớn, phức tạp thì vấn đề càng trờ nên khó khăn hơn. Khi ta muốn thay đổi, bổ sung cấu trúc dữ liệu dùng chung cho một số hàm/thủ tục thì phai thay đổi hầu như tất cả các hàm/thủ tục liên quan đến dữ liệu đó. > Mô hinh được xây dựng theo cách tiếp cận hướng thủ tục (TCHTT) không mô tả được đầy đủ, trung thực hệ thống trong thực tế. > Phương pháp TCHTT đặt trọng tâm vào hàm là hướng tói hoạt động sẽ không thực sự tương ứng với các thực thể trong hệ thống của thế giới thực. 1.1.3. Đặc điêm lập trình hưmig đối tượng Lập trình hướng đối tượng (Object Oriented Programming - OOP) là phương pháp lập trình lấy đối tượng làm nền tảng để xây dựng thuật giải, xây dựng chương trinh. Đối tượng được xây dựng trên cơ sở gắn cấu trúc dữ liệu với các phương thức (các hàm/thù tục) sẽ thể hiện được đúng cách mà chúng ta suy nghĩ, bao quát về thế giới thực. Lập trình hướng đối tượng (LTHĐT) cho phép ta kêt hợp n h ữ n g tri thức bao q uát v ề các quá trình với những khái niệm trừu tượng được sử dụng trong máy tính. Điểm căn bản của phương pháp LTHĐT là thiết kế chương trình xoay quanh dữ liệu của hệ thống. Nghĩa là các thao tác xử lý của hệ thống được gắn liền với dữ liệu và như vậy khi có sự thay đổi của cấu trúc dữ liệu thì chi ãnh hưởng đến một số ít các phương thức xử lý liên quan. LTHĐT không cho phép dữ liệu chuyển động tự do trong hệ thống. Dữ liệu được gan chặt với từng phương thức thành các vùng riêng mà các phương thức đó tác động lên và nó được báo vệ để cấm việc truy nhập tùy tiện từ bên 11 ngoài. LTHĐT cho phép phân tich bài toán thành tập các thực thể được aọi là các đối tượng và sau đó xây dựng các dữ liệu cùng với các phương thức xung quanh các đối tượng đó. Tóm lại LTHĐT có những đặc tính chủ yếu như sau: 1. Tập trung vào dữ liệu thay cho các phương thức. 2. Chương trinh được chia thành các lớp đối tượng. 3. Các cấu trúc dữ liệu được thiết kế sao cho đặc tả được các đối tượng 4. Các phương thức xác định trên các vùng dữ liệu của đối tượng được gắn với nhau trên cấu trúc dữ liệu đó 5. Dữ liệu được bao bọc, che giấu và không cho phép các thành phần bên ngoài truy nhập tự do. 6. Các đối tượng trao đổi với nhau thông qua các phương thức. 7. Dữ liệu và các phương thức mới có thể dễ dàng bổ sung vào đối tượng nào đó khi cần thiết. 8 Chương trinh được thiết kế theo cách tiếp cận bottom-up (duới - lên). 1.2. Các khái niệm cơ bản cùa lập trình hướng đối tưọng Những khái niệm cơ bàn trong LTHĐT bao gồm: Đối tượng; Lóp; Trừu tượng hóa dữ liệu, bao gói thông tin; Ke thừa; Tương ứng bội; Liên kết động; Truyền th ò n g báo 1.2.1. Đối tượììg Trong thế giới thực, khái niệm đối tượng được hiểu như là một thực thể, nó có thể là người, vật hoặc một bảng dữ liệu cần xử lý trong chương trình,... Trong LTHĐT thì đối tượng là biến thể hiện của lớp. 1.2.2. Lớp Lớp là một khái niệm mới trong LTHĐT so với kỹ thuật LTHTT. Nó là một bản mẫu mô tả các thông tin cấu trúc dữ liệu và các thao tác hợp lệ của các 12 phần tử dữ liệu. Khi một phần tử dữ liệu được khai báo là phần tử của một lớp thi nó được gọi là đoi tượng Các hàm được định nghĩa hợp lệ trong một lớp được gọi là các phương thức (method) và chúng là các hàm duy nhất có thể xử lý dữ liệu của các đối tượng của lớp đó. Chẳng hạn, chúng ta xét lớp HENH_CN bao gồm các thuộc tính: (xl,yl) toạ độ góc trên bên trái, d, r là chiều dài và chiều rộng của hình chữ nhật (HCN). Các phương thức nhập số liệu cho HCN, hàm tính diện tích, chu vi và hàm hiển thị. Lớp HINH_CN có thể được mô tả như sau: HINHCN Thuộc tính : X1 ,y 1 d,r Phưong thức: Nhập_sl Diện tích Chu vi Hiển thị Hình 1.1. Mô ta lóp HINH CN 1.2.3. Trừu tuỊ/rig hóa d ữ liệu và bao g ó i íỉtủtig tin Trừu tượng hóa là cách biểu diễn những đặc tính chính và bỏ qua những chi tiết nhỏ hoặc những giải thích. Khi xây dựng các lớp, ta phải sừ dụng khái niệm trừu tượng hóa. Ví dụ ta có thể định nghĩa một lớp để mô tả các đối tượng trong không gian hình học bao gồm các thuộc tính trừu tượng như là kích thước, hình dáng, màu sắc và các phương thức xác định trên các thuộc tính này. Việc đóng gói dữ liệu và các phương thức vào một đơn vị cấu trúc lớp được xem như một nguyên tắc bao gói thông tin. Dữ liệu được tổ chức sao cho thế giới bên ngoài (các đối tượng ờ lớp khác) không truy nhập vào, mà chỉ cho phép các phương thức trong cùng lớp hoặc trong những lớp có quan hệ kế thừa với nhau mới được quyền truy nhập. Chính các phương thức của lớp sẽ đóng vai ữò như là giao diện giữa dữ liệu của đối tượng và phần còn lại của chương trình. Nguyên tắc bao gói dữ liệu để ngân cấm sự truy nhập trực tiếp trong lập trinh được gọi là sự che giấu thông tin. 1.2.4. Kế thừa Kế thừa là quá trình mà các đối tượng cùa lớp này được quyền sử dụng một số tính chất của các đối tượng của lớp khác. Sự kế thừa cho phép ta định nghĩa một lớp mới trên cơ sỡ các lớp đã tồn tại. Lớp mới này, ngoài những thành phần được kế thừa, sẽ có thêm những thuộc tính và các hàm mới. Nguyên ]ý kế thừa hỗ ơợ cho việc tạo ra cấu trúc phân cấp các lớp. Ví dụ: Xây dựng một tập các lớp mô tả cho thư viện các ấn phẩm. Có hai kiểu ấn phẩm: tạp chí và sách. Chúng ta tạo một ấn phẩm tổng quát bằng cách định nghĩa các thành phần dữ liệu tương ứng với số trang, mã số tra tra cứu, ngày tháng xuất bản, bản quyền và nhà xuất bản. Các ấn phẩm có thể được lấy ra, cất đi và đọc. Đó là các phương thức thực hiện ữên một ẩn phẩm. Tiếp theo ta định nghĩa hai lớp dẫn xuất tên là tạp chí và sách. Tạp chí có tên, số kỳ phát hành và chứa nhiều bài của các tác giả khác nhau. Các thành phần dữ liệu tương ứng với các yếu tố này được đặt vào định nghĩa của lớp tạp chí. Tạp chí cũng cần có một phương thức nữa đó là đặt mua. Các thành phần dữ liệu xác định cho sách sê bao gồm tên của các lác giả, loại bìa và số hiệu ISBN cùa nó. Vậy có thể thấy, sách và tạp chí có chung các đặc trưng ấn phẩm, trong khi vẫn có các thuộc tinh riêng của chúng: 14 Án phẩm Số trang Mã số tra cứu Ngày tháng xuất bản Bản quyên Nhà xuất bàn Lấy ra Cất đi Đọc Tạp chí Sách Tên Tên của các tác giả Số kỳ phát hành Loại bìa Các bài viết ISBN Đăt mua Hình 1.2. Lớp ấn phấm và các lớp dẩn xuất cùa nó Với tính kế thừa, chúng ta không phải mất công xây dựng lại từ đẩu các lớp mới, chi cằn bổ sung để có được trong các lóp dẫn xuất các đặc trưng cần thiết. 1.2.5. Tương ứng bội Tương ứng bội là khả năng của một khái niệm (chẳng hạn các phép toán) có thể sử dụng với nhiều chức năng khác nhau. Ví dụ, phép + có thể biểu diễn cho phép “cộng” các số nguyên (int), số thực (float), số phức (complex) hoặc xâu ký tự (string) V.V.. Hành vi của phép toán tương ứng bội phụ thuộc vào kiều dữ liệu mà nó sử dụng để xử lý. Tương ứng bội đóng vai quan trọng trong việc tạo ra các đối tượng có cấu trúc bên trong khác nhau nhưng cùng dùng chung một giao diện bên ngoài (nhu tên gọi). Các bước tương ứng bội có thể tổng kết lại như sau: 1. Xây dựng lớp cơ sờ trừu tượng bao gồm những thuộc tính chung nhất của các thực thể cần quản lý. Đưa vào các phương thức ảo hay thuần ào dùng để xây dựng các nhóm phương thức ảo cho các lóp dẫn xuất sau này. Mỗi nhóm phương thức ảo sẽ thực hiện một chức năng nào đó trên các lớp. 2. Xây dựng các lớp dẫn xuất bắt đẩu từ lớp cơ sờ ảo. số mức dẫn xuất là không hạn chế. Các lớp dẫn xuất sẽ mô tả các đối tượng cụ thể cần quản lý. 3. Xây dựng các phương thức ảo trong các dẫn xuất. Các phương thức này tạo thành các nhóm phương thức ảo ưong sơ đồ các lớp có quan hệ thừa kế. 4. Xây dựng lớp quản lý các đối tượng. Dữ liệu của lớp này là một dãy con trỏ của lớp cơ sở trừu tượng ban đầu. Các con trò này có thể chứa địa chỉ đối tượng của các lớp dẫn xuất. Do vậy có thể dùng các con trỏ này để thực hiện các thao tác trên các đối tượng của bất kỳ lóp dẫn xuất nào. 1.2.6. Liên kết động Liên kết độ n g là dạng liên kết các thù tục và hàm khi chirang trình thực hiện led gọi tới các hàm, thủ tục đó. Như vậy ưong liên kết động, nội dung của đoạn chương trình ứng với thủ tục, hàm sẽ không được biết cho đến khi thực hiện lời gọi tới thủ tục, hàm đó. 1.2.7. Truyền thông báo Các đối tượng gừi và nhận thông tin với nhau giống như con người ữao đổi với nhau. Chính nguyên lý trao đổi thông tín bằng cách truyền thông báo cho phép ta dễ dàng xây dựng được hệ thống mô phòng gần hơn những hệ thống trong thế giới thực. Truyền thông báo cho một đối tượng là yêu cẩu đôi 16 tượng thực hiện một việc gi đó. Cách ứng xử của đối tượng được mô tả bên trong lớp thông qua các phương thức. Trong chương trình, thông báo gửi đến cho một đối tượng chinh là yêu cầu thực hiện một công việc cụ thể, nghĩa là sừ dụng những hàm tương ứng để xử lý dữ liệu đã được khai báo trong đối tượng đó. Vì vậy, trong thông báo phài chỉ ra được hàm cần thực hiện trong đối tượng nhận thông báo. Thông báo truyền đi cũng phải xác định tên đối tượng và thông tin truyền đi. Trong chương trình hướng đối tượng, mỗi đối tượng chi tồn tại trong thòi gian nhất định. Đối tượng được tạo ra khi nó được khai báo và sẽ bị hủy bỏ khi chương trình ra khỏi miền xác định của đối tượng đó. Sự trao đổi thông tin chi có thể thực hiện trong thời gian đối tuợng tồn tại. 1.3. Các bước cần thiết để thiết ke chưong trình theo hướng đối tượng Chương trinh theo hướng đối tượng bao gồm một tập các đối tượng và mối quan hệ giữa các đối tượng với nhau. Vì vậy, lập trình trong ngôn ngữ hướng đối tượng bao gồm các bước sau: 1 Xác định các dạng đối tượng (lớp) của bài toán (định dạng đối tượng). 2. Tim kiếm các đặc tính chung (dữ liệu chung) trong các dạng đối tượng này, những gi chúng cùng nhau chia sẻ. 3. Xác định được lớp cơ sờ dựa ữên cơ sờ các đặc tính chung của các dạng đối tượng. 4. Tú lớp cơ sớ, Sừ dụng quan hệ tỏng quat hoa dẻ dạc tá trong viẹc đưa các lớp dẫn xuất chứa các thành phần, những đặc tính không chung còn lại của các dạng đối tượng. Ngoài ra, ta còn đưa ra các lóp có quan hệ với các lớp cơ sờ và lớp dẫn xuất. Các quan hệ này có thể là quan hệ kết hợp, quan hệ tập hợp lại, quan hệ phụ thuộc. 1.4. Các ưu điếm của lập trình hướng đối tưọng Cách tiếp cận hướng đối tượng giải quyết được nhiều vấn đề tồn tại trong quá trinh phát triển phần mềm và tạo ra được những sản phẩm phần mềm có chất lượng cao. Những ưu điểm chính của LTHĐT là: 1. Thông qua nguyên ]ý kế thừa, có thể loại bò được những đoạn chương trình lặp lại trong quá trình mô tả các lớp và mờ rộng khả năng sử dụng các lớp đã được xây dựng. 2. Chương trinh được xây dựng từ những đơn thể (đối tượng) trao đổi với nhau nên việc thiết kế và lập trinh sẽ được thực hiện theo quy trình nhất định chứ không phải dựa vào kinh nghiêm và kỹ thuật như trước Điều này đảm bảo rút ngắn được thòi gian xây dựng hệ thống và tăng năng suất lao động. 3. Nguyên lý che giấu thông tin giúp người lập trinh tạo ra được những chương trình an toàn không bị thay bời những đoạn chương trình khác. 4. Có thể xây dựng được ánh xạ các đối tượng của bài toán vào đối tượng của chương trình. 5. Cách tiếp cận thiết kế đặt trọng tâm vào đối tượng, giúp chúng ta xây dựng được mô hinh chi tiết và gần với dạng cài đặt hơn 6. Những hệ thống hướng đối tượng dễ mờ rộng, nâng cấp thành những hệ lớn hơn. 7. Kỹ thuật truyền thông báo trong việc trao đổi thông tin giữa các đối tượng giúp cho việc mô tả giao diện với các hệ thống bên ngoài trở nên đơn giàn hơn. 8. Có thể quản lý được độ phức tạp của những sản phẩm phần mềm. Không phải trong hệ thống hướng đối tượng nào cũng có tất cả các tính chất nêu Ưên. Khả năng có các tính chất đó còn phụ thuộc vào lĩnh vực ứng dụng của dự án tin học và vào phương pháp thực hiện của người phát triển phần mềm. 1.5. Các ngôn ngữ hướng đối tượng Lập trình hướng đối tượng không là đặc quyền cũa một ngôn ngữ nào đặc biệt. Cũng giống như lập trình có cấu trúc, những khái niệm trong lập trinh hướng đối tượng có thể cài đặt Ưong những ngôn ngữ lập trình như c hoặc Pascal,. Tuy nhiên, đối với những chương trình lớn thỉ vấn đề lập trình sẽ trờ 18 nên phức tạp. Những ngôn ngữ được thiết kế đặc biệt, hỗ trợ cho việc mô tả, cài đặt các khái niệm của phương pháp hướng đối tượng được gọi chung là ngôn ngữ đối tượng. Dựa vào khả năng đáp ứng các khái niệm về hướng đối tượng, ta có thể chia ra làm hai loại: 1. Ngôn ngữ lập trinh dựa trên đối tượng 2. Ngôn ngữ lập trinh hướng đối tượng Lập trinh dựa trên đối tượng là kiểu lập trình hỗ trợ chinh cho việc bao gói, che giấu thông tin và định danh các đối tượng. Lập trình dựa trên đối tượng có những đặc tính sau: « Bao gói dữ liệu • Cơ chế che giấu và truy nhập dữ liệu • Tự động tạo lập và xóa bô các đối tượng • Phép toán tải bội Ngôn ngữ hỗ trợ cho kiểu lập trình trên được gọi là ngôn ngữ lập trinh dựa trên đối tượng. Ngôn ngữ trong lớp này không hỗ trợ cho việc thực hiện kế thừa và liên kết động, chẳng hạn Ada là ngôn ngữ lập trinh dựa ừên đối tượng. Lập trinh hướng đối tượng là kiểu lập trình dựa trên đối tượng và bổ sung thêm nhiều cấu trúc để cài đặt những quan hệ về ke thừa và liên kết động. Vì vậy đặc tính của LTHĐT có thể viết một cách ngắn gọn như sau: Các đặc tính dựa trên đối tượng + kế thừa + liên kết động. Ngôn ngữ hỗ trợ cho những đặc tính trên được gọi là ngôn ngữ LTHĐT, ví dụ như C++, Smalltalk, Object Pascal V.V.. Việc chọn một ngôn ngữ để cài đặt phần mềm phụ thuộc nhiều vào các đặc tính và yêu cầu của bài toán ứng dụng, vào khả năng sử dụng lại của những chương trình đã có và vào tổ chức của nhóm tham gia xây dựng phần mềm. 19 1.6. Một số ứng dụng của LTHĐT LTHĐT đang được ứng dụng để phát triển phẩn mềm trong nhiều lĩnh vực khác nhau. Trong số đó, có ứng dụng quan trọng và nổi tiếng nhất hiện nay là hệ điều hành Windows của hãng Microsoft đã được phát triển dựa trên kỹ thuật LTHĐT. Một số những lĩnh vực ứng dụng chính của kỹ thuật LTHĐT bao gồm: + Những hệ thống làm việc theo thời gian thực. + Trong lĩnh vực mô hình hóa hoặc mô phỏng các quá trinh + Các cơ sỡ dữ liệu hướng đối tượng. + Những hệ siêu văn bản, multimedia + Lĩnh vực trí tuệ nhân tạo và các hệ chuyên gia. + Lập trình song song và mạng nơ-ron. + Những hệ tự động hóa văn phòng và trợ giúp quyết định. 20 Chương 2 CÁC MỞ RỘNG CỦA NGÔN NGỮ c + + Chương 2 trình bày những vấn đề sau đây: > Giời thiệu chung về ngôn ngữ c — > Một số mơ rộng cua ngôn ngữ c — so với ngôn ngữ c > Các đặc tinh cua C - + hỗ trợ ìập trình hướng đối lượng > Vào ra trong C++ > Cấp phát và giai phóng bộ nhớ > Biến tham chiếu, hằng tham chiếu > Truvền tham so cho hàm theo tham chiếu > Hàm trà về giá trị tham chiếu > Hàm với tham số có giá trị mặc định > Các hàm nội tuyến (inỉine) > Hàm tai bội 2.1. Giới thiệu chung về C++ C++ là ngôn ngữ lập trình hướng đối tượng và là sự mờ rộng của ngôn ngữ c. Vì vậy mọi khái niệm trong c đều dùng được trong C++. Phần lớn các chương trình c đều có thể chạy được trong C++. Trong chương này chi tập trung giới thiệu những khái niệm, đặc tính mới của C++ hỗ trợ cho lập trình hướng đối tượng. Một số kiến thức có trong C++ nhưng đã có trong ngôn ngữ c sẽ không được trinh bày lại ờ đây. 21 2.2. Một số mở rộng của C++ so vói c 2.2.1. Đặí lời chú thích Ngoài kiểu chú thích trong c bằng /* ... * /, C++ đưa thêm một kiểu chú thich thứ hai, đó là chú thích bắt đầu bằng //. Kiểu chú thích /*...*/ được dùng cho các khối chú thích lớn gồm nhiều dòng, còn kiểu // được dùng cho các chú thích trên một dòng. Chương tnnh dịch sẽ bỏ qua tất cả các chú thích trong chương trình. Ví dụ: /* Đây là câu chú thích trên nhiều dòng */ // Đây là chú thích trên một dòng 2.2.2. Khai báo biến Trong c tất cả các câu lệnh khai báo biến, mảng cục bộ phải đặt tại đầu khối. Vì vậy vị trí khai báo và vị trí sử dụng của biến có thể ờ cách khá xa nhau, điều này gây khó khăn trong việc kiểm soát chương trình. C++ đã khắc phục nhược điểm này bằng cách cho phép các lệnh khai báo biến có thể đặt bất kỳ chỗ nào trong chương trinh trước khi các biến đuợc sử dụng. Phạm vi hoạt động của các biến kiểu này là khối trong đó biến đuợc khai báo Ví dụ 2.1. Chương trinh sau đây nhập một dãy số thực rồi sắp xếp theo thứ tự tăng dần: # i n c l ư d e <'stdio.h> #include #include void main() { int n; printf("\n So phan tu cua day N="); scanf{"%d",&n); 22 float *x=(float*)malloc((n+1)*sizeof(float)); for (int i=0;ix[j]) { float tg=x[i]; X[i]=x[j]; X [j]=tg; } printf("\n Day sau khi sap xep\n"); for (i=0;i #incluđe void main() { int n; printf("\n So phan tu cua day N="); scanf("%d",&n); float s=0.0; for (int i=l;i<=n;++i) s+= float(1)/float(i); //chuyen kieu theo C++ printf("s=%0.2f",s); getch(); } 2.2.4. Lấy địa chi các phần tứ màng thực 2 chiều Trong c không cho phép dùng phép toán & để lấy địa chỉ của các phần từ mảng thực 2 chiều. Vì vậy khi nhập một ma trận thực (dùng hàm scanf()) ta phải nhập qua một biến trung gian sau đó mới gán cho các phần tử mảng. C++ cho phép dùng phép toán & đề lấy địa chi các phần từ mảng thực 2 chiều, do đó thể dùng hàm scanf() để nhập trực tiếp vào các phần tử màng. Ví dụ 2.3. Chương trinh sau đây cho phép nhập một mảng thực cấp 20x20 và tìm các phần từ có giá trị lớn nhất. 24 #include #include void main() float a [20][20],smax; int ra,n,i,j,imax,jmax; clrscr(); puts(" Cho biet so hang va so cot cua ma tran: "); scanf("%d%d",&m,&n); for (i=0;i #include #include void main() { struct { char ht[25] ; float dl,d2,d3,td; }ts[100],tg; int n,i,j; clrscr (); cout « "So thi sinh:"; cin » n; for (i=0;i #include #include void main() { float a [50][50],smax; int m,n,i,j,imax,jmax; clrscr(); cout« "Nhap so hang va cot:"; cin»m»n; for (i=0;i #include #include 32 #include #include struct TS char ht[2 0]; long sobd; float td; } ; void main(void) TS *ts; int n; cout<<"\nSo thi sinh n = cin»n; ts = new TS[n+1]; if (ts == NULL) { cout << "\n Loi cap phat vung nho"; getch(); exit(0); } for (int i=0;i> ts[i].sobd; cout« "tong diem:"; cin»ts [i] . td; } for (i=0;i Biến tham chiếu và hằng tham chiếu khác nhau ở chỗ: không cho phép dùng hằng tham chiếu để làm thay đổi giá trị của vùng nhớ mà nó tham chiếu Ví dụ: int y=12, z; const int &p = y //Hằng tham chiếu p tham chiểu đến biến y p = p + 1; //Sai, trình biên dịch sẽ thông báo lỗi > Hằng tham chiếu cho phép sử dụng giá trị chứa trong một vùng nhớ, nhưng không cho phép thay đổi giá trị này. > Hằng tham chiếu thường được sử dụng làm tham số của hàm để cho phép sử dụng giá trị của các tham số trong lời gọi hàm, nhưng tránh làm thay đổi giá trị tham số. 2.7. Truyền tham số cho hàm theo tham chiếu Trong c chi cỏ một cách truyền dữ liệu cho hàm là truyền theo giá trị. Chương trình sẽ tạo ra các bản sao của các tham số thực sự trong lời gọi hàm và sẽ thao tác trên các bản sao này chứ không xử lý trực tiếp với các tham số thực sự. Cơ chế này rất tốt nếu khi thực hiện hàm trong chương trinh không cần làm thay đổi giá trị của biến gốc. Tuy nhiên, nhiều khi ta lại muốn những tham số đó thay đổi khi thực hiện hàm trong chương trinh. C++ cung cấp thêm cách truyền dữ liệu cho hàm theo tham chiếu bằng cách dùng đối là tham chiếu. Cách làm này có ưu diểm là không cần tạo ra các bản sao của các tham số, do dó tiết kiệm bộ nhớ và thời gian chạy máy. Mặt khác, hàm này sẽ thao 36 tác trực tiếp trên vùng nhớ của các tham số, do đó dễ dàng thay đồi giá trị các tham số khi cần. Ví dụ 2.7. Chương trình sau sẽ nhập dãy số thực, sẳp xếp dãy theo thứ tự tăng dần và hiển thị ra màn hình. #include #include #incluđe void nhapds(double *a,int n) { for(int i=0;ia[j]) hv(a [i ] , a [j ] ); } void main() { double X [100]; int i,n; clrscr(); cout«"\n nhap so phan tu N = cin>>n; nhapds(X,n); sapxep(X,n); cout<<"\nCac phan tu mang sau khi sap xep for(i=0;i #include #include #include struct TS { char ht [20]; float dl,d2,d3,tđ; } ; void ints(const TS Sts) { cout«setiosflags (ios: : showpoint) «setprecision (1) ; cout«"\n ho ten"«setw (20) « t s .ht«setw (6) « t s . td; void nhapsl(TS *ts,int n) { for(int i=0;i=dc) ints(ts [i]); 40 else break; getch(); } Ví dụ 2.9. Chương trinh sau sẽ nhập một mảng thực kích thước 20x20, in mảng đã nhập và in các phần tử lớn nhất và nhò nhất Ưẻn mỗi hàng của mảng. #include #include #include #include void nhapmt(float a [20][20],int m,int n) { for(int i=0;ix[vtmax]) vtmax=i; if(x[i]>n; nhapmt(a,m,n); inmt(a,m,n); float *p=(float*) a; int vtmax,vtmin; for(int i=0;i; } Trong trường hợp này biểu thức được trả lại trong câu lệnh return phải là ten cua mọt bién xac dinh rư ben ngoai ham, bơi VI khi đo m ơi co thè sứ dụng được giá trị của hàm. Khi ta trả về một tham chiếu đến một biến cục bộ khai báo bên trong hàm, biến cục bộ này sẽ bị mất đi khi kết thúc thực hiện hàm. Do vậy tham chiếu của hàm sẽ không còn ý nghĩa nữa. Khi giá trị trả về của hàm là tham chiếu, ta có thể gặp các câu lệnh gán hơi khác thường, trong đó vế trái là một lời gọi hàm chứ không phải là tên của một biến. Điều này hoàn toàn hợp lý, bời vi bản thân hàm đó có giá trị trả về là một tham chiếu. Nói cách khác, vế trái của lệnh gán có thể là lời gọi đến một hàm có giá trị trả về là một tham chiếu. Xem các ví dụ sau: 43 Vidu 2.10. #include #include int z; int Sf()// ham tra ve mot bi danh cua bien toan bo z { return z; } void main() f ()=50;//z=50 cout<<"\nz="< #include #include #include int & max(inti a, int& b); void main() { clrscr(); int b =10, a= 7, c= 20; cout « "Max a,b : "<b ? a:b; } Ket quả trên màn hình sẽ là: Max a,b : 10 Gia tri cua b va a : 11 7 Gia tri cua b va a va c : 11 7 5 2.9. Hàm vói tham số có giá trị mặc định C++ cho phép xây dựng hàm với các tham số được khởi gán giá trị mặc định. Quy tắc xây dựng hàm với tham số mặc định như sau: • Các đôi có giá trị mặc định cấn là các tham số cuối cùng tính từ trái qua phải. • Neu chương trình sử dựng khai báo nguyên mẫu hàm thì các tham số mậc định cần được khởi gán trong nguyên mẫu hàm, không được khởi gán lại cho các đối mặc định trong dòng đầu của định nghĩa hàm. void f(int a, float X, char *st="TRUNG TAM'', int b=l, double y = 1.234) ; 45 void f(int a, float X, c h a r *st="TRUNG TAM", int b=l, double y = 1.234) { //Các câu lệnh } • Khi xây dựng hàm, nếu không khai báo nguyên mẫu, thì các đối mặc định được khởi gán trong dòng đầu của định nghĩa hàm, ví dụ: void f(int a, float X, c h a r *st="TRUNG TAM", int b=l, double y = 1.234) { //Các câu lệnh } Chú ý: Đối với các hàm có tham số mặc định thì lời gọi hàm cần viết theo quy định: Các tham số vắng mặt trong lời gọi hàm tương ứng với các tham số mặc định cuối cùng (tính từ trái sang phải), ví dụ với hàm: void f(int a, float X, char *st=”TRUNG TAM”, int b=l, double y = 1.234); thì các lời gọi hàm đúng: f(3,3.4,”TIN HOC”, 10,1.0);//Đầy đủ tham số f(3,3.4,”ABC”); //Thiếu 2 tham số cuối f(3,3.4); //Thiếu 3 tham sô cuối Các lời gọi hàm sai: f(3); «3,3.4, ,10); Ví dụ 2.12. ttinclude #include 46 void ht(char *dc="TRUNG TAM",int n=5); void ht(char *dc,int n) { for(int i=0;i #include void main() { int s ; s=f(5,6) ; cout«s; getch(); } inline int f(int a,int b) { return a*b; } Chú ý: > Chương tnnh dịch các hàm inline như tương tự như các macro, nghĩa là nó sẽ thay đổi lời gọi hàm bằng một đoạn chương trình thực hiện nhiệm vụ hàm. Cách làm này sẽ tăng tốc độ chương trình do không phải thực hiện các thao tác có tính thủ tục khi gọi hàm nhưng lại làm tăng khối lượng bộ nhớ chương trình (nhất là đối với các hàm nội tuyến có nhiều câu lệnh). Vì vậy chi nên dùng hàm inline đối với các hàm có nội dung đơn giản. > Không phải khi gặp từ khoá inline là chương trình dịch nhất thiết phải xử lý hàm theo kiểu nội tuyến. Từ khoá inline chỉ là một từ khoá gợi ý cho chương trình dịch chứ không phải là một mệnh lệnh bắt buộc. 48 Ví dụ 2.14. Chương trinh sau sử dụng hàm inline đề tính chu vi và diện tích hinh chữ nhật. #include #include inline void dtcvhcn(int a,int b,int &dt,int ícv) { dt=a*b; cv=2*(a+b); } void main() { int a[20],b [20],cv[2 0],dt[20] , n; cout<<"\n So hinh chu nhat"; cin»n; for(int i=0;i>b [i] ; dtcvhcn(a[i],b [i],dt[i],cv[i]); } clrscr(); for(i=0;i #include inline void dtcvhcn(int a,int b,int &dt,int &CV) void main() int a[20],b [20],cv[20] ,dt[20] , n; cout«"\n So hinh chu nhat"; cin»n; forfint i=0;i #incluđe #include void nhapds(int *x,int n) ; void nhapds(double *x,int n) ; int max(int x,int y) ; double max(double x,double y) ; void nhapds(int *x,int n) { for(int i=0;i>x[i]; } } void nhapds(double *x,int n) { for (int i=0;iy?x:y; } double max(double x,double y) { return x>y?x:y; } int max(int *x,int n) { int s=x[0] ; for(int i=l;i Định nghĩa lớp > Tạo lập đối tượng > Trụy nhập đến các thành phần cùa lớp > Con tró đối tượng > Con tró this > Hàm bạn > Dữ liệu thành phần tĩnh, hàm thành phan lĩnh > Hàm tạo, hàm húy > Hàm tạo sao chép Lớp là khái niêm trung tâm của lâp trình hướng đối tuợng, nó là sư mờ rộng của các khái niệm cấu trúc (struct) của c. Ngoài các thành phần dữ liệu, lớp còn chứa các thành phần hàm, còn gọi là phương thức (method) hoặc hàm thành viên (member function). Lóp có thể xem như một kiểu dữ liệu các biến, mảng đối tượng. Từ một lớp đã định nghĩa, có thể tạo ra nhiều đối tượng khác nhau, mỗi đối tượng có vùng nhớ riêng. Chương này sẽ trình bày cách định nghĩa lớp, cách xây dựng phương thức, giải thích về phạm vi truy nhập, sử dụng các thành phần của lớp, cách khai báo biến, mảng cấu trúc, lời gọi tới các phương thức. 58 3.1. Định nghĩa lóp Cú pháp: Lớp được định nghĩa theo mẫu : class tên_lớp { private: [Khai báo các thuộc tính] [Định nghĩa các hàm thành phần (phương thức)] public : [Khai báo các thuộc tinh] [Định nghĩa các hàm thành phần (phương thức)] }; Thuộc tính của lớp được gọi là dữ liệu thành phần và hàm được gọi là phương thức hoặc hàm thành viên. Thuộc tính và hàm được gọi chung là các thành phần của lớp. Các thành phần của lớp được tổ chức thành hai vùng: vùng sở hữu riêng (private) và vùng dùng chung (public) để quy định phạm vi sử dụng của các thành phần. Nếu không quy định cụ thể (không dùng các từ khóa private và public) thì C++ hiểu đó là private. Các thành phần private chi được sừ dụng bên trong lớp (trong thân của các hàm thành phần). Các thành phần public được phép sừ dụng ở cả bên trong và bên ngoài lớp. Các hàm không phải là hàm thành phần của lớp thì không được phép sử dụng các thành phần này. Khai báo các thuộc tính của lớp được thực hiện y như việc khai báo biến. Thuộc tinh của lớp không thể có kiểu chính của lớp đó, nhưng có thể là kiểu con trò của lớp này, Ví dụ: class A { A x; //Không cho phép, vi X có kiểu lớp A 59 A *p ; // Cho phép, vi p là con trỏ kiểu lớp A }; Định nghĩa các hàm thành phần: Các hàm thành phần có thể được xây dựng bên ngoài hoặc bên trong định nghĩa lớp. Thông thường, các hàm thành phần đơn giản, có ít dòng lệnh sẽ được viết bên trong định nghĩa lớp, còn các hàm thành phần dài thì viết bên ngoài định nghĩa lớp. Các hàm thành phẩn viết bên ữong định nghĩa lớp được viết như hàm thông thương. Khi định nghĩa hàm thành phần ở bên ngoài lớp, ta dùng cú pháp sau đây: Kiểu_trà_về_của_hàm Tên_lớp::Tên_hàm(khai báo các tham số) { [nội dune hàm] } Toán tử :: được gọi là toán tử phân giải miền xác định, được dùng để chỉ ra lớp mà hàm đó thuộc vào. Trong thản hàm thành phần, có thể sử dụng các thuộc tính của lớp, các hàm thành phần khác và các hàm tự do trong chương trình. Chú ý : • Các thành phần dữ liệu khai báo là private nhằm bảo đảm nguyên lý che giấu thông tin, bảo vệ an toàn dữ liệu của lớp, không cho phép các hàm bên ngoài xâm nhập vào dữ liệu của lớp. • Các hàm thành phần khai báo là public có thể được gọi tới từ các hàm thành phần public khác trong chương trình. 3.2. Tạo lập đối tưọng Sau khi định nghĩa lớp, ta có thể khai báo các biến thuộc kiểu lớp. Các biến này được gọi là các đối tượng. Cú pháp khai báo biến đối tượng như sau: Tên_lớp Danh_sách_biến; 60 Đối tượng cũng có thể khai báo khi định nghĩa lớp theo cú pháp sau: class tên_lớp { } ; Mỗi đối tượng sau khi khai báo sẽ được cấp phát một vùng nhớ riêng để chứa các thuộc tính của chúng. Không có vùng nhớ riêng để chứa các hàm thành phẩn cho mỗi đối tượng. Các hàm thành phần sẽ được sừ dụng chung cho tất cả các đối tượng cùng lớp. 3.3. Truy nhập tới các thành phần của lóp • Để truy nhập đến dữ liệu thành phần của lớp, ta dùng cú pháp: Tên_đối_tuợng. Tên_thuộc_tính Cần chú ý rằng dữ liệu thành phẩn riêng chỉ có thể được truy nhập bởi những hàm thành phần của cùng một lớp, đối tượng cùa lớp cũng không thể truy nhập. • Đe sử dụng các hàm thành phần của lớp, ta dùng cú pháp: Tên_đối_tượng.Tên_hàm(Các_khai_báo_tham_số_thực_sự) Ví dụ 3.1. # in c lu d e < co n io .h > # in c lu d e < io stre a m .h > c la s s DIEM { p r iv a te : i n t x ,y ; p u b lic : 61 void nhapsl( ) { cout « "\n Nhap hoarih do va tung do cua diem:" cin >>x>>y ; } void hienthi( ) { cout«"\n x = " « x « " y = "< #include class A { int m,n; public : void nhap( ) { cout « "\n Nhap hai so nguyen : " cin»m>>n ; } int max() { return m>n?m:n; } void hienthi( ) { cout<<"\n Thanh phan du lieu lon nhat X «max () < #include #include class phrase { private: char dongtu[10]; char danhtu[10]; char cumtu[25]; public: phrase(); inline void set_danhtu(char* in_danhtu); inline void set_dongtu(char* in_dongtu); inline char* get_phrase(void); }; void phrase::phrase() { strcpy(danhtu,""); strcpy(dongtu,""); strcpy(cumtu,""); } inline void phrase::set_danhtu(char* in_danhtu) { strcpy(danhtu, in_danhtu); } inline void phrase::set_dongtu(char* in_dongtu) { strcpy(dongtu, in_dongtu); } inline char* phrase::get_phrase(void) { strcpy(cumtu,dongtu); 66 strcat(cumtu," the "); strcat(cumtu,danhtu); return cumtu; } void main() { phrase text; cout « "Cum tu la : -> " « text. get_phrase () « "\n"; text.set_danhtu("file"); cout << "Cum tu la : -> " « text.get_phrase()<<"\n"; text.set_dongtu("Save"); cout « "Cum tu la : -> " « text.get_phrase()<<"\n"; text.set_danhtu("program"); cout « "Cum tu la : -> " « text.get_phrase()<<"\n" ; } Kết quả chương trình như sau: Cum tu la : -> the Cum tu la : -> the file Cum tu la : -> Save the file Cum tu la : -> Save the program Ví dụ 3.5. Ví dụ sau minh họa việc sử dụng từ khóa const trong lớp: #include #include class constants 67 private: int number; public: void print_it(const int data_value); }; void constants::print_it(const int data_value) { number = data_value; cout « number « "\n"; void main() { constants num; const int START = 3; const int STOP= 6; int index; for (index=START; index<=STOP; index++) { cout« "index = " ; num.print_it(index); cout« "START = " ; num.print_it(START); } getch(); } Kết quả chương trinh như sau: index = 3 START = 3 index = 4 START = 3 index = 5 START = 3 68 index = 6 START = 3 3.4. Con trỏ đối tượng Con trỏ đối tượng dùng để chứa địa chỉ của biến đối tượng, được khai báo như sau : Tên lớp * Tên_con_ trỏ ; Ví dụ: Dùng lớp DIEM, ta có thể khai báo: DIEM *pl, *p2, *p3 ; / / Khai báo 3 con trò p 1, p2, p3 DIEM d 1, d2 ; //Khai báo hai đối tuợng d 1, d2 DIEM d [20]; // Khai báo mảng đối tượng Có thể thực hiện câu lệnh : pl = &d2 ; //pl chứa địa chi của d2, pl trỏ tới d2 p2 =d ; // p2 trò tới đầu mảng d p3 =new DIEM //tạo một đối tượng và chứa địa chi của nó vào p3 Để truy xuất các thành phần của lớp từ con trò đối tượng, ta viết như sau: Tên_con_ưò -> Tên_thuộc_tính Tên_con_trò -> Tên_hàm(các tham số thực sự) Nêu con trỏ chứa đâu địa chì của mảng, có thé dùng con trò như tên màng. Ví dụ 3.6. #include #include class mhang { int maso; float gia; public: void getdata(int a, float b) {maso= a; gia= b;} void show() { cout << "maso" « maso« endl; cout « "gia" « gia<< endl; } } ; const int k=5; void main() { clrscr(); mhang *p = new mhang[k]; mhang *d = p; int x,i; float y; cout«"\nNhap vao du lieu 5 mat hang for (i = 0; i getdata(x,y); p++;} for (i = 0; i show (); d++; } getch(); } 3.5. Con trỏ this Mỗi hàm thành phần của lớp có một tham số ẩn, đó là con trỏ this. Con trỏ this trỏ đến từng đối tượng cụ thể. Ta hãy xem lại hàm nhapsl() của lớp DIEM trong ví dụ ờ trên: void nhapsl( ) { cout « "\n Nhap hoanh do va tung do cua diem : cin >>x>>ỵ; } Trong hàm này ta sử dụng tên các thuộc tính x,y một cách đơn độc. Điều này dường như mâu thuẫn với quy tắc sử dụng thuộc tinh. Tuy nhiên nó được lý giải như sau: C++ sừ dụng một con trò đặc biệt trong các hàm thành phần. Các thuộc tính viết trong hàm thành phần được hiểu là thuộc một đối tượng do con trỏ this trô tới. Như vậy, hàm nhapsio có thể viết một cách tường minh như sau: void nhapsl() { cout« "\n Nhap hoanh do va tung do cua diem:"; cin » th is-> x » th is-> y ; } Con trò this là đối thứ nhất của hàm thành phần. Khi một iời gọi hàm thành phần được phát ra bời một đối tượng thì tham số tmyền cho con trò this chính là địa chỉ của đối tượng đó. 71 Ví dụ: Xét một lời gọi tới hàm nhapsio : DIEM dl ; dl.nhapsl(); Trong trường hợp này của dl thì this =&dl. Do đó this -> X chính là dl.x và this-> y chinh là dl.y Chú ý: Ngoài tham số đặc biệt this không xuất hiện một cách tường minh, hàm thành phần lớp có thể có các tham số khác được khai báo như trong các hàm thông thường. Ví dụ 3.7. #include ciostream.h> #include class time { int h,m; public : void nhaptint hi, int ml) { h= hi; m = ml;} void hienthi(void) { cout « h « " gio " « m « " phut"«endl;} void tong(time, time); } ; void time::tong(time tl, time t2) { m= tl.m+ t2.m; //this->m = tl.m+ t2.m; h= m/60; //this->h = this->m/60; m= m%60; //this->m = this->m%60; h = h+tl.h+t2.h; //this->h = this->h + tl.h+t2.h; 72 } void main() { clrscr (); time obi, ob2,ob3; obi.nhap(2,45); ob2.nhap(5,40); ob3.tong(obi,ob2); cout <<"object 1 = obi.hienthi(); cout <<"object 2 = ob2. hienthi(); cout «"object 3 = ob3. hienthi(); getch(); } Chương trình cho kết quả như sau : object 1 = 2 gio 45 phut object 2 = 5 gio 40 phut object 3 = 8 gio 25 phut 3.6. Hàm bạn Trong thực tế thường xảy ra trường hợp có một số lớp cần sử dụng chung một hàm. C++ giải quyết vấn đề này bằng cách dùng hàm bạn. Để một hàm trờ thành bạn của một lớp, có 2 cách viết: Cách 1: Dùng từ khóa friend để khai báo hàm trong lớp và xây dựng hàm bên ngoài như các hàm thông thường (không dùng từ khóa friend). Mầu viết như sau: 73 class A { private : // Khai báo các thuộc tinh public : // Khai báo các hàm bạn của lớp A friend void f1 (...) ; friend double f2 (...) ; } ; // Xây dựng các hàm f l , f2, f3 void f1 (...) { } double f2 (...) { } Cách 2: Dùng từ khóa friend để xây dựng hàm trong định nghĩa lớp. Mau viết như sau : class A { private : 74 // Khai báo các thuộc tinh public : // Khai báo các hàm bạn cùa lớp A void f1 (...) { } double f2 (...) { } } ; Hàm bạn có những tính chất sau: - Hàm bạn không phải là hàm thành phần của lớp. - Việc truy nhập tới hàm bạn được thực hiện như hàm thông thường. - Trong thân hàm hạn của một lrrp có thể tniy nhập tới các thuộc tính cùa đối tượng thuộc lớp này. Đây là sự khác nhau duy nhất giữa hàm bạn và hàm thông thường. - Một hàm có thề là bạn của nhiều lớp. Lúc đó nó có quyền truy nhập tới tất cả các thuộc tinh của các đối tượng trong các lớp này. Để làm cho hàm f trờ thành bạn của các lớp A, B và c ta sừ dụng mẩu viết sau : class B ; //Khai báo trước lớp A class B ; // Khai báo trước lớp B 75 class c ; // Khai báo trước lớp c // Định nghĩa lóp A class A { // Khai báo f là bạn của A friend void f (... ) } ; // Định nghĩa lóp B class B { // Khai báo f là bạn cùa B friend void f (...) } ; // Định nghĩa lóp c class c { // Khai báo f là bạn cùa c f r i e n d v o i d f (...) } ; // xây dựng hàm f void f (...) { } ; 76 Vi du 3.8. #include #include class sophuc {float a,b; public : sophuc() {} sophuc(float x, float y) {a=x; b=y;} friend sophuc tong(sophuc,sophuc); friend void hienthi(sophuc); } ; sophuc tong(sophuc cl,sophuc c2) {sophuc c3; c3.a=cl.a + c2.a ; c3.b=cl.b + c2.b ; return (c3); } void nienthl(sopnuc c) {cout«c.a<<" + "<