Bài giảng Lập trình hướng đối tượng Phần 1

pdf 87 trang Gia Huy 17/05/2022 2390
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Lập trình hướng đối tượng Phần 1", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pdfbai_giang_lap_trinh_huong_doi_tuong_phan_1.pdf

Nội dung text: Bài giảng Lập trình hướng đối tượng Phần 1

  1. LËp tr×nh h•íng ®èi t•îng MỤC LỤC Mục lục 1 Chương 1: Lập trình hướng đối tượng và C++ 5 1.1. Lập trình hướng đối tượng là gì 5 1.2. Các ngôn ngữ và một vài ứng dụng hướng đối tượng 5 1.3. Một số khái niệm trong lập trình hướng đối tượng 6 1.3.1. Sự đóng gói 6 1.3.2. Lớp và thực thể 7 1.3.3. Tính thừa kế 7 1.3.4. Tính đa hình 7 1.3.5. Phương thức ảo 8 1.4. Một số mở rộng đơn giản trong C++ so với C 8 1.4.1. Môi trường C++ 8 1.4.2. Lập trình cấu trúc và lập trình hướng đối tượng 9 1.4.3. Cách viết dòng ghi chú 11 1.4.4. Khai báo linh hoạt và hằng có kiểu 12 1.4.5. Các kiểu char và int 13 1.4.6. Lấy địa chỉ các phần tử mảng thực hai chiều 13 1.4.7.Vào ra trong C++ 14 1.4.8. Cấu trúc trong C++ 15 1.4.9. Cấp phát bộ nhớ trong C++ 15 1.5. Hàm trong C++ 19 1.5.1. Biến tham chiếu 19 1.5.2. Truyền giá trị cho hàm theo biến tham chiếu 20 1.5.3. Hàm trả về các tham chiếu 20 1.5.4. Đối có giá trị mặc định 21 1.5.5. Các hàm trực tuyến (inline) 21 1.5.6. Định nghĩa chồng các hàm 22 1.5.7. Định nghĩa chồng các toán tử 22 Câu hỏi và Bài tập 31 Chương 2: Lớp và đối tượng 39 2.1. Định nghĩa lớp 39 2.2. Phạm vi truy xuất 40 2.3. Đối tượng 41 2.3.1. Biến, mảng đối tượng 41 2.3.2. Con trỏ đối tượng 42 Trang - 1 -
  2. LËp tr×nh h•íng ®èi t•îng 2.3.3. Đối của phương thức, con trỏ this 42 2.4. Hàm và các phương thức của lớp 43 2.4.1. Hàm và hàm bạn 43 2.4.2. Phương thức toán tử 49 2.4.3. Hàm tạo 54 2.4.4. Lớp không có hàm tạo và hàm tạo mặc định 55 2.4.5. Hàm tạo sao chép 58 2.4.6. Hàm huỷ 61 2.4.7. Toán tử gán 63 2.4.8. Phân loại các phương thức 64 2.4.9. Hàm tạo và đối tượng thành phần 65 2.5. Các thành phần tĩnh 70 2.5.1. Thành phần dữ liệu tĩnh 70 2.5.2. Phương thức tĩnh 73 2.6. Khởi gán mảng đối tượng 75 2.7. Cấp phát bộ nhớ cho đối tượng 76 2.8. Đối tượng hằng, phương thức hằng 76 2.9. Hàm bạn, lớp bạn 81 Câu hỏi và bài tập 82 Chương 3: Dẫn xuất và thừa kế 88 3.1. Sự dẫn xuất và tính thừa kế 88 3.1.1. Lớp cơ sở và lớp dẫn xuất 88 3.1.2. Cách xây dựng lớp dẫn xuất 88 3.1.3. Các kiểu thừa kế 89 3.1.4. Thừa kế các thành phần dữ liệu 90 3.1.5. Thừa kế phương thức 91 3.2. Hàm tạo và hàm huỷ đối với tính thừa kế 95 3.2.1. Xây dựng hàm tạo của lớp dẫn xuất 95 3.2.2. Hàm huỷ của lớp dẫn xuất 98 3.3. Phạm vi truy xuất đến các thành phần của lớp cơ sở 100 3.4. Thừa kế nhiều mức và sự trùng tên 104 3.4.1. Sơ đồ xây dựng các lớp dẫn xuất theo nhiều mức 104 3.4.2. Sự thừa kế nhiều mức 105 3.4.3. Sự trùng tên 105 3.4.4. Sử dụng các thành phần trong lớp dẫn xuất 106 3.5. Lớp cơ sở ảo 107 3.5.1. Một số lớp cơ sở xuất hiện nhiều lần trong lớp dẫn xuất 107 Trang - 2 -
  3. LËp tr×nh h•íng ®èi t•îng 3.5.2. Các lớp cơ sở ảo 107 3.6. Toán tử gán của lớp dẫn xuất 108 3.6.1. Khi nào cần xây dựng toán tử gán 108 3.6.2. Cách xây dựng toán tử gán cho lớp dẫn xuất 108 3.7. Hàm tạo sao chép của lớp dẫn xuất 108 3.7.1. Khi nào cần xây dựng hàm tạo sao chép 108 3.7.2. Cách xây dựng hàm tạo sao chép cho lớp dẫn xuất 109 3.8. Phương thức tĩnh 110 3.9. Sự hạn chế của phương thức tĩnh 112 3.10. Phương thức ảo và tương ứng bội 112 3.10.1. Cách định nghĩa phương thức ảo 112 3.10.2. Quy tắc gọi phương thức ảo 113 3.10.3. Tương ứng bội 116 3.10.4. Liên kết động 119 3.10.5. Quy tắc gán địa chỉ đối tượng cho con trỏ lớp cơ sở 130 3.11. Lớp cơ sở trừu tượng 130 Câu hỏi và bài tập 135 Chương 4: Khuôn hình 141 4.1. Khuôn hình hàm 141 4.1.1. Khái niệm khuôn hình hàm 141 4.1.2. Tạo một khuôn hình hàm 141 4.1.3. Sử dụng khuôn hình hàm 142 4.1.4. Các tham số kiểu của khuôn hình hàm 145 4.1.5. Giải thuật sản sinh một hàm thể hiện 146 4.1.6. Khởi tạo các biến có kiểu dữ liệu chuẩn 147 4.1.7. Các hạn chế của khuôn hình hàm 148 4.1.8. Các tham số biểu thức của một khuôn hình hàm 149 4.1.9. Định nghĩa chồng các khuôn hình hàm 150 4.2. Khuôn hình lớp 152 4.2.1. Khái niệm khuôn hình lớp 152 4.2.2. Tạo một khuôn hình lớp 153 4.2.3. Sử dụng khuôn hình lớp 158 4.2.4. Các tham số trong khuôn hình lớp 158 4.2.5. Các tham số biểu thức trong khuôn hình lớp 160 4.2.6. Tổng quát về khuôn hình lớp 162 4.2.7. Cụ thể hoá khuôn hình lớp 162 4.2.8. Sự giống nhau của các lớp thể hiện 165 Trang - 3 -
  4. LËp tr×nh h•íng ®èi t•îng 4.2.9. Các lớp thể hiện và các lớp bạn bè 166 Câu hỏi và bài tập 173 Chương 5: Các dòng xuất nhập 174 5.1. Các lớp stream 174 5.2. Dòng cin và toán tử nhập 175 5.3. Dòng cout và toán tử xuất 176 5.4. Các phương thức định dạng 178 5.4.1. Nội dung định dạng giá trị xuất 178 5.4.2. Các phương thức định dạng 180 5.5. Cờ định dạng 182 5.5.1. Khái niệm chung về cờ 182 5.5.2. Công dụng của các cờ 182 5.5.3. Các phương thức bật tắt cờ 186 5.6. Các dòng tin chuẩn 187 5.7. Ghi dữ liệu lên tệp 187 5.8. Đọc dữ liệu từ tệp 193 5.9. Đọc ghi dữ liệu đồng thời trên tệp 197 Câu hỏi và bài tập 244 Một số thông báo lỗi thường gặp 248 Tài liệu tham khảo 253 Trang - 4 -
  5. LËp tr×nh h•íng ®èi t•îng Chương 1: Lập trình hướng đối tượng và C++ Nội dung của chương tập trung trình bày các vấn đề sau: Lập trình hướng đối tượng là gì? Một số khái niệm trong lập trình hướng đối tượng. Giới thiệu về C++ và một số mở rộng của C++ so với C. Hàm trong C++. 1.1. Lập trình hướng đối tượng là gì Vào những ngày đầu phát triển của máy tính, khi các phần mềm còn rất đơn giản chỉ cỡ vài chục dòng lệnh, chương trình được viết tuần tự với các câu lệnh được thực hiện từ đầu đến cuối. Cách lập trình như vậy được gọi là phương pháp lập trình tuyến tính. Khoa học máy tính ngày càng phát triển, các phần mềm đòi hỏi ngày một phức tạp và lớn hơn rất nhiều. Vì vậy, xuất hiện một phương pháp lập trình mới gọi là lập trình cấu trúc. Theo phương pháp này, chương trình được tổ chức thành các chương trình con. Mỗi chương trình con đảm nhận xử lý một công việc nhỏ trong toàn bộ hệ thống. Mỗi chương trình con này lại có thể chia nhỏ thành các chương trình con nhỏ hơn. Quá trình phân chia như vậy cứ tiếp diễn cho tới khi các chương trình con nhận được là đủ đơn giản để giải quyết. Người ta gọi quá trình đó là “làm mịn dần”. Theo quan điểm của phương pháp này: Chương trình = Cấu trúc dữ liệu + Giải thuật. Vì vậy, để lập được một chương trình đòi hỏi người lập trình phải có kiến thức vững vàng về Cấu trúc dữ liệu. Một khó khăn nữa gặp phải là chương trình phụ thuộc chặt chẽ vào cấu trúc dữ liệu. Do vậy, chỉ cần một thay đổi nhỏ ở cấu trúc dữ liệu có thể phải viết lại cả chương trình, điều này không thích hợp khi xây dựng một dự án phần mềm lớn. Một phương pháp lập trình đang được sử dụng phổ biến hiện nay đã khắc phục được nhược điểm này của phương pháp lập trình cấu trúc đó chính là lập trình hướng đối tượng. Lập trình hướng đối tượng đặt trọng tâm vào các đối tượng (dữ liệu của hệ thống), không cho phép dữ liệu biến động tự do trong hệ thống. Lập trình hướng đối tượng có những đặc điểm chủ yếu sau: - Tập trung vào dữ liệu thay cho các hàm - Chương trình được chia thành các đối tượng - Cấu trúc dữ liệu được thiết kế sao cho đặc tả được đối tượng - Các hàm thao tác trên các vùng dữ liệu của đối tượng được gắn với cấu trúc dữ liệu đó Trang - 5 -
  6. LËp tr×nh h•íng ®èi t•îng - Dữ liệu được đóng gói lại, được che dấu và không cho phép các hàm ngoại lai truy nhập tự do - Các đối tượng tác động và trao đổi thông tin với nhau qua các hàm - Có thể dễ dàng bổ sung dữ liệu và các hàm mới vào đối tượng nào đó khi cần thiết. 1.2. Các ngôn ngữ và một vài ứng dụng hướng đối tượng Lập trình hướng đối tượng không phải là đặc quyền của một ngôn ngữ lập trình đặc biệt nào. Cũng giống như kỹ thuật lập trình có cấu trúc, các khái niệm trong lập trình hướng đối tượng được thể hiện trong nhiều ngôn ngữ lập trình khác nhau. Những ngôn ngữ cung cấp được những khả năng lập trình hướng đối tượng (tạo lớp, đối tượng, thừa kế, ) được gọi là ngôn ngữ lập trình hướng đối tượng. Một số ngôn ngữ lập trình hướng đối tượng đang dùng phổ biến hiện nay như: C++, Java, C#, Visual Basic.Net, Lập trình là một trong những thuật ngữ được nhắc đến nhiều nhất hiện nay trong công nghệ phần mềm và nó được ứng dụng để phát triển phần mềm trong nhiều lĩnh vực khác nhau. Trong số đó, ứng dụng quan trọng và nổi tiếng nhất hiện nay là thiết kế giao diện với người sử dụng, kiểu như Windows. Các lĩnh vực ứng dụng phù hợp với kỹ thuật lập trình hướng đối tượng có thể liệt kê như dưới đây:  Các hệ thống làm việc theo thời gian thực;  Các hệ mô hình hoá hoặc mô phỏng các quá trình;  Các hệ cơ sở dữ liệu hướng đối tượng;  Các hệ siêu văn bản (hypertext), đa phương tiện (multimedia);  Các hệ thống trí tuệ nhân tạo và các hệ chuyên gia;  Các hệ thống song song và mạng nơ-ron;  Các hệ tự động hoá văn phòng hoặc trợ giúp quyết định;  Các hệ CAD/CAM.  1.3. Một số khái niệm trong lập trình hướng đối tượng 1.3.1. Sự đóng gói Trong phương pháp lập trình cấu trúc các hàm hay thủ tục có phạm vi hoạt động trong toàn bộ chương trình, nó được sử dụng thông qua các lời gọi mà không cần Trang - 6 -
  7. LËp tr×nh h•íng ®èi t•îng biết đến nội dung cụ thể của nó. Người sử dụng chỉ cần biết chức năng của hàm cũng như các tham số cần truyền vào để gọi hàm chạy mà không cần quan tâm đến những lệnh cụ thể bên trong nó. Người ta gọi đó là sự đóng gói về chức năng. Trong phương pháp lập trình hướng đối tượng, không những các chức năng được đóng gói mà cả dữ liệu cũng như vậy. Với mỗi đối tượng người ta không thể truy nhập trực tiếp vào các thành phần dữ liệu của nó mà phải thông qua các thành phần chức năng (các phương thức) để làm việc đó. 1.3.2. Lớp và thực thể Đối tượng (hay thực thể) là sự kết hợp giữa dữ liệu và thủ tục (hay còn gọi là phương thức - method) thao tác trên dữ liệu đó. Có thể đưa ra công thức phản ánh bản chất kỹ thuật của lập trình hướng đối tượng như sau: Đối tượng = Dữ liệu + Phương thức Lớp là một tập các đối tượng có cấu trúc dữ liệu và các phương thức giống nhau (hay nói cách khác là một tập các đối tượng cùng loại). Như vậy, khi có một lớp thì sẽ biết được một mô tả cấu trúc dữ liệu và phương thức của các đối tượng thuộc lớp đó. Mỗi đối tượng sẽ là một thể hiện cụ thể (instance) của lớp đó. Trong lập trình, có thể coi một lớp như là một kiểu dữ liệu, còn các đối tượng sẽ là các biến có kiểu của lớp. 1.3.3. Tính thừa kế Tính thừa kế là khả năng cho phép định nghĩa một lớp mới trên cơ sở các lớp đã tồn tại, tất nhiên có bổ sung những phương thức hay các thành phần dữ liệu mới. Khả năng thừa kế cho phép dễ dàng chỉnh sửa và phát triển chương trình. Rõ ràng đây là một điểm mạnh của lập trình hướng đối tượng so với lập trình cấu trúc. 1.3.4. Tính đa hình Đó là khả năng cho phép một thông điệp (lời gọi phương thức) có thể thay đổi cách thực hiện của nó theo lớp cụ thể của đối tượng nhận lời gọi phương thức. Khi một lớp dẫn xuất được tạo ra, nó có thể thay đổi cách thực hiện các phương thức nào đó mà nó thừa hưởng từ lớp cơ sở của nó. Một lời gọi phương thức từ đối tượng của lớp cơ sở, sẽ thực hiện phương thức đó trong lớp cơ sở. Nếu một lớp dẫn xuất định nghĩa lại một phương thức thừa hưởng từ lớp cơ sở của nó thì một lời gọi phương thức cùng tên với phương thức này, khi được gửi tới một đối tượng của lớp dẫn xuất sẽ gọi phương thức đã định nghĩa cho lớp dẫn xuất. Trang - 7 -
  8. LËp tr×nh h•íng ®èi t•îng 1.3.5. Phương thức ảo C++ cũng cho phép cơ chế tương ứng bội bằng cách định nghĩa một phương thức là phương thức ảo trong sơ đồ thừa kế. Khi đó, một con trỏ lớp cơ sở có thể trỏ đến địa chỉ của một đối tượng lớp dẫn xuất, và phương thức được thực hiện là tuỳ thuộc vào kiểu của đối tượng mà con trỏ đang trỏ tới. 1.4. Một số mở rộng đơn giản trong C++ so với C 1.4.1. Môi trường C++ C là một ngôn ngữ lập trình mạnh và linh hoạt được sử dụng rộng rãi để giải các bài toán khoa học kỹ thuật, ghép nối máy tính, đồ hoạ, Để thừa kế những điểm mạnh vốn có của C vào năm 1983, giáo sư Bjarne Stroustrap bắt đầu nghiên cứu và phát triển việc cài đặt khả năng lập trình hướng đối tượng vào ngôn ngữ C tạo ra một ngôn ngữ mới gọi là C++. Hai dấu + trong tên gọi C++ thể hiện hai đặc điểm mới của C++ so với C. Đặc điểm thứ nhất là một số khả năng mở rộng so với C như tham chiếu, chồng hàm, tham số mặc định Đặc điểm thứ hai chính là khả năng lập trình hướng đối tượng. Hiện nay C++ chưa phải là một ngôn ngữ hoàn toàn ổn định. Kể từ khi phiên bản đầu tiên ra đời vào năm 1986 đã có rất nhiều thay đổi trong các phiên bản C++ khác nhau: bản 1.1 ra đời vào năm 1986, 2.0 vào năm 1989 và 3.0 vào năm 1991. Phiên bản 3.0 này được sử dụng để làm cơ sở cho việc định nghĩa một ngôn ngữ C++ chuẩn (kiểu như ANSI C). Trên thực tế hiện nay tất cả các chương trình dịch C++ đều tương thích với phiên bản 3.0. Vì vậy C++ hầu như không gây bất kỳ một khó khăn nào khi chuyển đổi từ một môi trường này sang môi trường khác. C++ chứa đựng khái niệm lớp. Một lớp bao gồm các thành phần dữ liệu bao gồm các thuộc tính và các phương thức( hay là hàm thành phần). Từ một lớp có thể tạo ra các đối tượng hoặc bằng cách khai báo thông thường một biến có kiểu là lớp đó hoặc bằng cách cấp phát bộ nhớ động nhờ sử dụng toán tử new. C++ cho phép đóng gói dữ liệu nhưng nó không bắt buộc chúng ta thực hiện điều đó. Đây là một nhược điểm của C++. Tuy nhiên cũng cần thấy rằng bản thân C++ chỉ là sự mở rộng của C nên nó không thể là một ngôn ngữ lập trình hướng đối tượng thuần khiết được. C++ cho phép định nghĩa các hàm tạo (constructor) cho một lớp. Hàm tạo là một phương thức đặc biệt được gọi đến tại thời điểm một đối tượng của lớp được tạo ra. Trang - 8 -
  9. LËp tr×nh h•íng ®èi t•îng Hàm tạo có nhiệm vụ khởi tạo một đối tượng: cấp phát bộ nhớ, gán các giá trị cho các thành phần dữ liệu cũng như việc chuẩn bị chỗ cho các đối tượng mới. Một lớp có thể có một hay nhiều hàm tạo. Để xác định hàm tạo nào cần gọi đến, chương trình biên dịch sẽ so sánh các đối số với các tham số truyền vào. Tương tự như hàm tạo, một lớp có thể có một hàm huỷ (destructor), một phương thức đặc biệt được gọi đến khi đối tượng được giải phóng khỏi bộ nhớ. Lớp trong C++ thực chất là một kiểu dữ liệu do người sử dụng định nghĩa. Khái niệm định nghĩa chồng toán tử cho phép định nghĩa các phép toán trên một lớp giống như các kiểu dữ liệu chuẩn của C. Ví dụ chúng ta có thể định nghĩa một lớp số phức với các phép toán cộng, trừ, nhân, chia. Cũng giống như C, C++ có khả năng chuyển đổi kiểu. Không những thế, C++ còn cho phép mở rộng sự chuyển đổi này sang các kiểu do người sử dụng tự định nghĩa (các lớp). Ví dụ, chúng ta có thể chuyển đổi từ kiểu chuẩn int của C sang kiểu số phức mà ta định nghĩa chẳng hạn. C++ cho phép thực hiện thừa kế các lớp đã xây dựng. Từ phiên bản 2.0 trở đi, C++ còn cho phép một lớp thừa kế cùng một lúc từ nhiều lớp khác nhau (gọi là sự đa thừa kế). Cuối cùng C++ cung cấp những thao tác vào ra mới dựa trên cơ sở khái niệm luồng dữ liệu (flow). Sự ưu việt của các thao tác này ở chỗ: * Sử dụng đơn giản. * Kích thước bộ nhớ được rút gọn. * Khả năng áp dụng trên các kiểu do người sử dụng định nghĩa bằng cách sử dụng cơ chế định nghĩa chồng toán tử. 1.4.2. Lập trình cấu trúc và lập trình hướng đối tượng Đặc trưng của lập trình hướng cấu trúc Trong lập trình hướng cấu trúc, chương trình chính được chia nhỏ thành các chương trình con và mỗi chương trình con thực hiện một công việc xác định. Chương trình chính sẽ gọi đến chương trình con theo một giải thuật, hoặc một cấu trúc được xác định trong chương trình chính. Các ngôn ngữ lập trình cấu trúc phổ biến là Pascal, C và C++. Riêng C++ ngoài việc có đặc trưng của lập trình cấu trúc Trang - 9 -
  10. LËp tr×nh h•íng ®èi t•îng do thừa kế từ C, còn có đặc trưng của lập trình hướng đối tượng. Cho nên C++ còn được gọi là ngôn ngữ lập trình nửa cấu trúc, nửa hướng đối tượng. Đặc trưng cơ bản nhất của lập trình cấu trúc thể hiện ở mối quan hệ: Chương trình = Cấu trúc dữ liệu + Giải thuật Cấu trúc dữ liệu là cách tổ chức dữ liệu cho việc xử lý bởi một hay nhiều chương trình nào đó. Giải thuật là một quy trình để thực hiện một công việc xác định. Trong chương trình, giải thuật có quan hệ phụ thuộc vào cấu trúc dữ liệu: Một cấu trúc dữ liệu chỉ phù hợp với một số hạn chế các giải thuật. Nếu thay đổi cấu trúc dữ liệu thì phải thay đổi giải thuật cho phù hợp. Một giải thuật thường phải đi kèm với một cấu trúc dữ liệu nhất định. Tính chất Mỗi chương trình con có thể được gọi thực hiện nhiều lần trong một chương trình chính. Các chương trình con có thể được gọi đến để thực hiện theo một thứ tự bất kì, tuỳ thuộc vào giải thuật trong chương trình chính mà không phụ thuộc vào thứ tự khai báo của các chương trình con. Các ngôn ngữ lập trình cấu trúc cung cấp một số cấu trúc lệnh điều khiển chương trình. Ưu điểm Chương trình sáng sủa, dễ hiểu, dễ theo dõi. Tư duy giải thuật rõ ràng. Nhược điểm Lập trình cấu trúc không hỗ trợ mạnh việc sử dụng lại mã nguồn: Giải thuật luôn phụ thuộc chặt chẽ vào cấu trúc dữ liệu. Do đó, khi thay đổi cấu trúc dữ liệu, phải thay đổi giải thuật, nghĩa là phải viết lại chương trình. Không phù hợp với các phần mềm lớn: tư duy cấu trúc với các giải thuật chỉ phù hợp với các bài toán nhỏ, nằm trong phạm vi một module của chương trình. Với dự án phần mềm lớn, lập trình cấu trúc tỏ ra không hiệu quả trong việc giải quyết mối quan hệ vĩ mô giữa các module của phần mềm. Đặc trưng của lập trình hướng đối tượng Trong lập trình hướng đối tượng: Ta coi các thực thể trong chương trình là các đối tượng và sau đó trừu tượng hoá đối tượng thành lớp đối tượng. Trang - 10 -
  11. LËp tr×nh h•íng ®èi t•îng Dữ liệu được tổ chức thành các thuộc tính của lớp. Nguời ta ngăn chặn việc thay đổi tuỳ tiện dữ liệu trong chương trình bằng các cách giới hạn truy nhập như chỉ cho phép truy nhập dữ liệu thông qua đối tượng, thông qua các phương thức mà đối tượng được cung cấp Quan hệ giữa các đối tượng là quan hệ ngang hàng hoặc quan hệ thừa kế: Nếu lớp B thừa kế từ lớp A thì A được gọi là lớp cơ sở và B được gọi là lớp dẫn xuất. Lập trình hướng đối tượng có hai đặc trưng cơ bản: Đóng gói dữ liệu: dữ liệu luôn được tổ chức thành các thuộc tính của lớp đối tượng. Việc truy nhập đến dữ liệu phải thông qua các phương thức của đối tượng lớp. Sử dụng lại mã nguồn: việc sử dụng lại mã nguồn được thể hiện thông qua cơ chế thừa kế. Cơ chế này cho phép các lớp đối tượng có thể thừa kế từ các lớp đối tượng khác. Khi đó, trong các lớp dẫn xuất, có thể sử dụng các phương thức (mã nguồn) của các lớp cơ sở mà không cần phải định nghĩa lại. Lập trình hướng đối tượng có một số ưu điểm nổi bật: Không còn nguy cơ dữ liệu bị thay đổi tự do trong chương trình vì dữ liệu đã được đóng gói vào các đối tượng. Nếu muốn truy nhập vào dữ liệu phải thông qua các phương thức được cho phép của đối tượng. Khi thay đổi cấu trúc dữ liệu của một đối tượng, không cần thay đổi mã nguồn của các đối tượng khác, mà chỉ cần thay đổi một số thành phần của đối tượng dẫn xuất. Điều này hạn chế sự ảnh hưởng xấu của việc thay đổi dữ liệu đến các đối tượng khác trong chương trình. Có thể sử dụng lại mã nguồn, tiết kiệm tài nguyên, chi phí thời gian vì nguyên tắc thừa kế cho phép các lớp dẫn xuất sử dụng các phương thức từ lớp cơ sở như những phương thức của chính nó, mà không cần thiết phải định nghĩa lại. Phù hợp với các dự án phần mềm lớn, phức tạp. 1.4.3. Cách viết dòng ghi chú Trong một chương trình cần thiết có các lời chú thích, ngoài cách viết các lời chú thích như trong C, trong C++ ta sử dụng // để viết lời chú thích trên một dòng. Mọi Trang - 11 -
  12. LËp tr×nh h•íng ®èi t•îng ký hiệu đi sau “//” cho đến hết dòng được coi là chú thích, được chương trình dịch bỏ qua khi biên dịch chương trình. Ví dụ: cin>>n; //nhap gia tri cho n tu ban phim 1.4.4. Khai báo linh hoạt và hằng có kiểu Trong C++ không nhất thiết phải nhóm lên đầu các khai báo đặt bên trong một hàm hay một khối lệnh, mà có thể đặt xen kẽ với các lệnh xử lý. Ví dụ 1.1: #include #include void main() { int x,y; cout >x; cout >y; int tong ; tong = x+y; cout<<”Tong hai so la:”<<tong; getch(); } thËm chÝ ta cã thÓ khai b¸o biÕn trong c¸c khèi lÖnh if, for, while. Ch¼ng h¹n nh• : for(int i = 1 ; i <= n ; i++) §Ó t¹o mét h»ng cã kiÓu sö dông tõ kho¸ const ®Æt tr•íc mét khai b¸o cã khëi g¸n gi¸ trÞ. VÝ dô 1.2: const int max= 100; struct Diem { int x,y; }; const Diem d = {10, 10}; Trang - 12 -
  13. LËp tr×nh h•íng ®èi t•îng 1.4.5. C¸c kiÓu char vµ int Trong C mét h»ng ký tù ®•îc xem lµ nguyªn do ®ã nã cã kÝch th•íc b»ng 2 byte. Cßn trong C++ mét h»ng ký tù ®•îc xem lµ gi¸ trÞ kiÓu char vµ cã kÝch th•íc b»ng mét byte. Nh• vËy, trong C++ th× sizeof(„A‟) = sizeof(char) = 1 1.4.6. LÊy ®Þa chØ c¸c phÇn tö m¶ng thùc hai chiÒu Ng«n ng÷ lËp tr×nh C kh«ng cho phÐp dïng to¸n tö & ®Ó lÊy ®Þa chØ phÇn tö m¶ng thùc hai chiÒu. V× vËy, khi nhËp gi¸ trÞ cho phÇn tö m¶ng thùc hai chiÒu ph¶i sö dông mét biÕn phô cã kiÓu thùc. Tr•íc tiªn ta nhËp gi¸ trÞ cho biÕn phô, sau ®ã, ta lÊy gi¸ trÞ biÕn phô ®ã ®Ó g¸n cho phÇn tö m¶ng thùc cÇn nhËp. VÝ dô 1.3: trong C ta viÕt: void nhap(float A[20][20], int n) { float x; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { printf(“A[%d][%d] = “,i+1, j+1) scanf(“%f”, &x); A[i,j] = x; } } C++ cho phÐp lÊy ®Þa chØ m¶ng thùc hai chiÒu sö dông to¸n tö &. V× vËy, cã thÓ dïng scanf ®Ó nhËp trùc tiÕp vµo c¸c phÇn tö m¶ng. void nhap(float A[20][20], int n) { for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) { printf(“A[%d][%d] = “,i+1, j+1) scanf(“%f”, &A[i,j]); } } Trang - 13 -
  14. LËp tr×nh h•íng ®èi t•îng 1.4.7.Vào ra trong C++ Các hàm vào/ra của C đều có thể sử dụng trong C++. Để sử dụng các hàm này chúng ta chỉ cần khai báo tệp tiêu đề stdio.h trong đó có chứa khai báo hàm nguyên mẫu của chúng. Bên cạnh đó, C++ còn cài đặt thêm các khả năng vào/ra mới dựa trên hai toán tử “>>”(nhập) và “ >” và “ >” để nhập dữ liệu cho các biến có kiểu char, int, float, double và char * như sau: cin>>biến_1>>biến_2>> >>biến_n; Ví dụ 1.4: Chương trình sau nhập vào 2 số nguyên và in ra màn hình tổng của hai số đó #include #include void main() { int so1,so2; cout >so1; cout >so2; cout<<”Tong hai so la:”<<so1+so2; getch(); } Trang - 14 -
  15. LËp tr×nh h•íng ®èi t•îng 1.4.8. Cấu trúc trong C++ C++ vẫn chấp nhận khai báo kiểu cấu trúc như trong C. Ngoài ra, C++ còn cho phép khai báo kiểu cấu trúc theo cú pháp: struct tên_kiểu { KiÓu_dl Tr•êng_1; KiÓu_dl Tr•êng_1; KiÓu_dl Tr•êng_1; } ; mµ kh«ng cÇn ph¶i sö dông tõ kho¸ typedef nh• trong C. VÝ dô 1.5: struct product { int weight; float price; } ; product apple; product banana, melon; 1.4.9. Cấp phát bộ nhớ trong C++ Ngoài các hàm cấp phát bộ nhớ như malloc, realloc, calloc như trong C, C++ cung cấp toán tử new để cấp phát bộ nhớ và toán tử delete để giải phóng bộ nhớ được cấp phát bởi toán tử new. Toán tử new thay thế cho hàm malloc() hay calloc() của C, có cú pháp như sau: new Kiểu_dữ_liệu Nếu kiểu dữ liệu mô tả phức tạp, nó có thể được đặt bên trong các dấu ngoặc. Nếu toán tử new cấp phát không thành công thì nó sẽ trả về giá trị NULL. Chúng ta có thể vừa cấp phát vừa khởi động như sau : Con_trỏ = new Kiểu_dl(Giá_trị); Ví dụ 1.6: int *P; P = new int(100); Toán tử delete thay thế hàm free() của C, nó có cú pháp như sau : delete Con_trỏ; Trang - 15 -
  16. LËp tr×nh h•íng ®èi t•îng delete [] Con_trỏ; Để cấp phát một mảng, chúng ta làm như sau : Con_trỏ = new Kiểu_dữ_liệu[Kích_thước_mảng] ; Ví dụ 1.7: int *P; P = new int[10]; //Cấp phát mảng 10 số nguyên Chú ý: Đối với việc cấp phát mảng chúng ta không thể vừa cấp phát vừa khởi gán giá trị cho chúng, chẳng hạn đoạn chương trình sau là sai : int *P; P = new (int[10])(3); //Sai !!! Ví dụ 1.8: Sử dụng kiểu cấu trúc, các toán tử new, delete trong việc cài đặt một số phép toán trên danh sách nối kép. #include #include struct node //khai bao cau truc mot nut trong ds noi kep { int info; node *lptr; node *rptr; }; node *l,*r; void create(int n)//t¹o lËp danh s¸ch nèi kÐp l•u tr÷ n sè nguyªn { node *p;int x; for(int i=1;i lptr=NULL; p->rptr=NULL; cout >p->info; if(l==NULL) l=r=p; else { Trang - 16 -
  17. LËp tr×nh h•íng ®èi t•îng r->rptr=p; p->lptr=r; r=p; } } } void ht()//hiÓn thÞ c¸c sè nguyªn trong danh s¸ch { node *p; p=l; while(p!=NULL) { cout info rptr; } } node *tim(int x)//t×m ®Þa chØ nót cã info = x cho tr•íc { node *p; p=l; while((p!=NULL)&&(p->info!=x)) p=p->rptr; return p; } void insert(node *m,int x) //bæ sung nót cã info = x vµo tr•íc nót trá bëi m trong ds { node *p; p=new node; p->info=x; p->lptr=NULL; p->rptr=NULL; if((r ==NULL)&&(l==NULL)) l=r=p; else if(l==m) {p->rptr=m;m->lptr=p; l=p;} Trang - 17 -
  18. LËp tr×nh h•íng ®èi t•îng else { p->rptr=m; p->lptr=m->lptr; (m->lptr)->rptr=p; m->lptr=p; } } void del(int x)//xo¸ khái danh s¸ch nót cã info = x (nÕu cã) { node *p; p=tim(x); if(p!=NULL) { if(l==r) l=r=NULL; else if(l==p) { l=p->rptr; l->lptr=NULL;} else if (r==p) {r=p->lptr;r->rptr=NULL;} else { (p->lptr)->rptr=p->rptr; (p->rptr)->lptr=p->lptr; } delete p; } } void main() { int x,n; char tl; node *p; cout >n; create(n); cout<<"Danh sach vua nhap\n"; Trang - 18 -
  19. LËp tr×nh h•íng ®èi t•îng ht(); do { cout >x; p=tim(x); cout >x; insert(p,x); cout >x; del(x); cout >tl; } while(tl!='k'); getch(); } 1.5. Hàm trong C++ 1.5.1. Biến tham chiếu Biến tham chiếu là biến có đặc điểm: - Không được cấp phát bộ nhớ, không có địa chỉ riêng; - Dùng làm bí danh cho một biến nào đó và sử dụng vùng bộ nhớ của biến này. Để khai báo biến tham chiếu ta sử dụng cú pháp: Kiểu_dữ_liệu &Biến_tham_chiếu = Biến_được_tham_chiếu; Trong đó, biến được tham chiếu có thể là một phần tử mảng, hoặc một biến nhớ nhưng nó phải là một biến cụ thể đã tồn tại. Ví dụ 1.9: float u,v, &r = u; Trong ví dụ này, r là biến tham chiếu, biến được tham chiếu là biến u, hay r là bí danh của u. Khi đó câu lệnh: r = r +1 sẽ tăng giá trị của biến u lên 1. Trang - 19 -
  20. LËp tr×nh h•íng ®èi t•îng 1.5.2. Truyền giá trị cho hàm theo biến tham chiếu Trong C++ khi dùng đối số là biến tham chiếu sẽ làm cho hàm thao tác trực tiếp trên vùng nhớ của các tham số do đó sẽ dễ dàng thay đổi giá trị của các tham số khi cần. Ví dụ 1.10: void swap(int &x, int &y) { int temp = x; x = y; y = temp} Hàm swap đã sử dụng hai đối x, y là các biến tham chiếu. Khi đó, hàm có thể làm thay đổi giá trị của tham số thực được truyền cho hàm. Việc truyền tham số cho hàm sử dụng biến tham chiếu giống như việc truyền tham số sử dụng biến nhớ thông thường khác. Ví dụ, để gọi hàm swap ta viết: swap(a, b); 1.5.3. Hàm trả về các tham chiếu Hàm có thể trả về giá trị tham chiếu hoặc có kiểu tham chiếu. Khi đó, có thể dùng hàm để truy nhập đến một biến hoặc một phần tử mảng nào đó. Định nghĩa của hàm có giá trị trả về là tham chiếu có dạng như sau: & fct( ) { return ; } Trong trường hợp này biểu thức được trả lại trong câu lệnh return phải là tên của một biến xác định từ bên ngoài hàm, bởi vì chỉ khi đó mới có thể sử dụng được giá trị của hàm. Khi 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 và do vậy, tham chiếu của hàm cũng không còn có ý 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 “kỳ dị” 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 lẽ 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 (biểu thức 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. Ví dụ 1.11: Trang - 20 -
  21. LËp tr×nh h•íng ®èi t•îng Khai báo một hàm f trả về tham chiếu đến một biến toàn cục z và do đó, ta có thể dùng hàm f để truy nhập đến biến z này. #include #include int z; int &f() { return z; } void main() { f() = 10; f() = f() +1; cout<<”z = “<<z; getch(); } 1.5.4. §èi cã gi¸ trÞ mÆc ®Þnh §èi cã gi¸ trÞ mÆc ®Þnh lµ ®èi cã thÓ cã mÆt hoÆc kh«ng cã mÆt trong lêi gäi hµm. C¸c ®èi nµy ®•îc khëi g¸n gi¸ trÞ ngay tõ khi khai b¸o nguyªn mÉu cña hµm, chóng ph¶i lµ c¸c ®èi ®•îc khai b¸o sau cïng tÝnh tõ tr¸i sang ph¶i trong danh s¸ch ®èi cña hµm. VÝ dô 1.12: float Trong_luong( float m, float g = 9.8) { return m*g; } Khi gäi hµm Trong_luong ta cã thÓ truyÒn cho hµm mét tham sè (Trong_luong(m)) hoÆc cã thÓ truyÒn ®ñ c¶ hai tham sè (Trong_luong(m, g)). Trong tr•êng hîp chØ truyÒn mét tham sè th× hµm sÏ sö dông gi¸ trÞ 9.8 cho tham sè thø hai. 1.5.5. C¸c hµm trùc tuyÕn (inline) Mét hµm sÏ lµ hµm trùc tuyÕn nÕu cã tõ khãa inline tr•íc dßng tiªu ®Ò cña hµm. VÝ dô 1.13: inline myFunction(int n); Trang - 21 -
  22. LËp tr×nh h•íng ®èi t•îng Khi sö c¸c hµm trong mét ch•¬ng tr×nh C hoÆc C++ th•êng th× phÇn th©n hµm sau khi ®•îc biªn dÞch sÏ lµ mét tËp c¸c lÖnh m¸y. Mçi khi ch•¬ng tr×nh gäi tíi hµm, ®o¹n m· cña hµm sÏ ®•îc n¹p vµo stack ®Ó thùc hiÖn sau ®ã tr¶ vÒ 1 gi¸ trÞ nµo ®ã nÕu cã vµ th©n hµm ®•îc lo¹i khái stack thùc hiÖn cña ch•¬ng tr×nh. NÕu hµm ®•îc gäi 10 lÇn sÏ cã 10 lÖnh nh¶y t•¬ng øng víi 10 lÇn n¹p th©n hµm ®Ó thùc hiÖn. Víi tõ kho¸ inline chóng ta muèn gîi ý cho tr×nh biªn dÞch lµ thay v× n¹p th©n hµm nh• b×nh th•êng h·y chÌn ®o¹n m· cña hµm vµo ®óng chç mµ nã ®•îc gäi tíi trong ch•¬ng tr×nh. §iÒu nµy râ rµng lµm cho ch•¬ng tr×nh thùc hiÖn nhanh h¬n b×nh th•êng. Tuy nhiªn inline chØ lµ mét gîi ý vµ kh«ng ph¶i bao giê còng ®•îc thùc hiÖn h¬n n÷a nã lµm t¨ng kÝch bé nhí cho ch•¬ng tr×nh. Víi c¸c hµm phøc t¹p (ch¼ng h¹n nh• cã vßng lÆp) th× kh«ng nªn dïng inline mµ chØ nªn dïng víi c¸c hµm ®¬n gi¶n, ch¼ng h¹n nh• c¸c hµm chØ thùc hiÖn khëi t¹o gi¸ trÞ cho c¸c biÕn. 1.5.6. §Þnh nghÜa chång c¸c hµm C++ cho phÐp lËp tr×nh viªn cã kh¶ n¨ng viÕt c¸c hµm cã tªn gièng nhau, kh¶ n¨ng nµy ®•îc gäi lµ chång hµm (overload). VÝ dô chóng ta cã thÓ cã c¸c hµm nh• sau: int myFunction(int); int myFunction(int, int); int myFunction(int, int, int); C¸c hµm overload cÇn tho¶ m·n mét ®iÒu kiÖn lµ danh s¸ch c¸c tham sè cña chóng ph¶i kh¸c nhau (vÒ sè l•îng tham sè vµ hoÆc kiÓu tham sè). KiÓu c¸c hµm overload cã thÓ gièng nhau hoÆc kh¸c nhau. Danh s¸ch kiÓu c¸c tham sè cña mét hµm ®•îc gäi lµ ch÷ ký (signature) cña hµm ®ã. Víi c¸c hµm lín vµ phøc t¹p chóng ta nªn sö dông chång hµm, ngoµi ra viÖc sö dông c¸c hµm chång nhau còng lµm cho ch•¬ng tr×nh s¸ng sña vµ dÔ gì lçi h¬n. 1.5.7. §Þnh nghÜa chång c¸c to¸n tö C++ cho phÐp thùc hiÖn c¸c phÐp to¸n (+, -, *, /, ) trªn c¸c kiÓu d÷ liÖu kh«ng ph¶i kiÓu d÷ liÖu chuÈn (®•îc gäi lµ kiÓu d÷ liÖu ng•êi dïng tù ®Þnh nghÜa). ViÖc khai b¸o c¸c hµm thùc hiÖn c¸c phÐp to¸n trªn kiÓu d÷ liÖu ng•êi dïng tù ®Þnh nghÜa ®•îc gäi lµ ®Þnh nghÜa chång to¸n tö. Khi ®ã, ta cã c¸c hµm ®•îc gäi lµ hµm to¸n tö. C¸ch ®Þnh nghÜa hµm to¸n tö: Tªn hµm: operator tiÕp sau lµ phÐp to¸n Trang - 22 -
  23. LËp tr×nh h•íng ®èi t•îng VÝ dô: operator+ §èi cña hµm to¸n tö: §èi víi to¸n tö hai ng«i hµm cÇn cã hai ®èi, ®èi víi to¸n tö mét ng«i hµm cÇn mét ®èi. VÝ dô: Matran operator+(Matran x, Matran y) Th©n cña hµm to¸n tö: ViÕt nh• hµm th«ng th•êng C¸ch gäi hµm to¸n tö: Cã hai c¸ch Gäi nh• hµm th«ng th•êng. VÝ dô: z = operator+(a,b); Gäi nh• c¸ch sö dông phÐp to¸n. VÝ dô: z = x+y VÝ dô 1.14: #include #include struct Phanso { int tuso, mauso; }; void Nhap(Phanso &x) { cout >x.tuso; do { cout >x.mauso; }while (x.mauso == 0); } void Hienthi(Phanso x) { cout<<x.tuso<<”/”<<x.mauso<<”\n”; } Phanso operator+(Phanso x, Phanso y) { Phanso kq; kq.tuso = x.tuso*y.mauso + y.tuso*x.mauso; kq.mauso = x.mauso*y.mauso; return kq; } Phanso operator-(Phanso x, Phanso y) { Phanso kq; Trang - 23 -
  24. LËp tr×nh h•íng ®èi t•îng kq.tuso = x.tuso*y.mauso - y.tuso*x.mauso; kq.mauso = x.mauso*y.mauso; return kq; } Phanso operator*(Phanso x, Phanso y) { Phanso kq; kq.tuso = x.tuso*y.tuso; kq.mauso = x.mauso*y.mauso; return kq; } Phanso operator/(Phanso x, Phanso y) { Phanso kq; kq.tuso = x.tuso*y.mauso; kq.mauso = x.mauso*y.tuso; return kq; } void main() { Phanso x, y, z; Nhap(x); Nhap(y); z = x + y; cout<<”\nTong hai phan so la:”; Hienthi(z); z = x - y; cout<<”\nHieu hai phan so la:”; Hienthi(z); z = x * y; cout<<”\nTich hai phan so la:”; Hienthi(z); z = x / y; cout<<”\nThuong hai phan so la:”; Trang - 24 -
  25. LËp tr×nh h•íng ®èi t•îng Hienthi(z); getch(); } VÝ dô 1.15: ViÕt ch•¬ng tr×nh khai b¸o cÊu tróc ®a thøc bËc n, viÕt c¸c hµm vµ hµm to¸n tö thùc hiÖn c¸c c«ng viÖc sau: a. NhËp vµo bËc vµ c¸c hÖ sè cña ®a thøc b. HiÓn thÞ ®a thøc ra mµn h×nh c. TÝnh gi¸ trÞ cña ®a thøc t¹i x = a, a lµ mét sè thùc nhËp tõ bµn phÝm d. TÝnh tæng hai ®a thøc e. TÝnh hiÖu hai ®a thøc f. TÝnh tÝch hai ®a thøc #include #include #include #define max 100 struct dathuc { int bac; float heso[max]; }; void nhap(dathuc &p) { cout >p.bac; for(int i=0;i >p.heso[i]; } } void hienthi(dathuc p) { for(int i=p.bac;i>0;i ) { cout<<p.heso[i]<<"x^"<<i; Trang - 25 -
  26. LËp tr×nh h•íng ®èi t•îng if(p.heso[i-1]>=0) cout q.bac) { kq.bac = p.bac; for(int i=0;i =0)) kq.bac=kq.bac-1; return kq; } dathuc operator-(dathuc p, dathuc q) Trang - 26 -
  27. LËp tr×nh h•íng ®èi t•îng { dathuc kq; if(p.bac > q.bac) { kq.bac = p.bac; for(int i=0;i =0)) kq.bac=kq.bac-1; return kq; } dathuc operator*(dathuc p,dathuc q) { dathuc kq; kq.bac=p.bac+q.bac; for(int i=0;i<=kq.bac;i++) kq.heso[i]=0; for(i=0;i<=p.bac;i++) for(int j=0;j<=q.bac;j++) kq.heso[i+j]+=p.heso[i]*q.heso[j]; return kq; } void main() { dathuc p,q,r; Trang - 27 -
  28. LËp tr×nh h•íng ®èi t•îng nhap(p); cout >/ > vµ > ®Ó nhËp th«ng tin mét thÝ sinh vµ to¸n tö #include #include struct ts { char sbd[5]; char ten[30]; Trang - 28 -
  29. LËp tr×nh h•íng ®èi t•îng unsigned int diem; }; ostream &operator >(istream &is, ts &t) { cout >t.diem; is.ignore(); return is; } void main() { ts ds[100]; int n,i; cout >n; cin.ignore(1);//xo¸ bé nhí ®Öm bµn phÝm for(i=1;i >ds[i]; } cout<<"\nDanh sach thi sinh\n"; for(i=1;i<=n;i++) cout<<ds[i]<<"\n"; getch(); Trang - 29 -
  30. LËp tr×nh h•íng ®èi t•îng } Trang - 30 -
  31. LËp tr×nh h•íng ®èi t•îng C©u hái vµ Bµi tËp 1. Trong c¸c khai b¸o con trá sau, nh÷ng khai b¸o nµo lµ ®óng: a. int A*; b. *int A; c. int* A, B; d. int* A, *B; e. int *A, *B; 2. Víi khai b¸o: int a = 12; int *pa; c¸c phÐp g¸n nµo sau ®©y lµ hîp lÖ: a. pa = &a; b. pa = a; c. *pa = &a; d. *pa = a; 3. Víi khai b¸o: int A[5] = {10, 20, 30, 40, 50}; int *pa = A+2; khi ®ã, *pa = ? a. 10 b. 20 c. 30 d. 40 e. 50 4. Víi ®o¹n ch•¬ng tr×nh: int A[5] = {10, 20, 30, 40, 50}; int *pa = A; *pa += 2; khi ®ã, *pa = ? a. 10 b. 12 c. 30 d. 32 5. Víi ®o¹n ch•¬ng tr×nh: Trang - 31 -
  32. LËp tr×nh h•íng ®èi t•îng int A[5] = {10, 20, 30, 40, 50}; int *pa = A; pa += 2; khi ®ã, *pa = ? a. 10 b. 12 c. 30 d. 32 6. Víi ®o¹n ch•¬ng tr×nh: int A[5] = {10, 20, 30, 40, 50}; int *pa = A; pa += 2; khi ®ã, pa = ? a. &A[0] b. A[2] c. &A[2] d. Kh«ng x¸c ®Þnh 7. Víi ®o¹n ch•¬ng tr×nh: int A[5] = {10, 20, 30, 40, 50}; int *pa = A; pa -= 2; khi ®ã, pa = ? a. &A[0] b. &A[2] c. &A[4] d. Kh«ng x¸c ®Þnh 8. Víi ®o¹n ch•¬ng tr×nh: int A[3][3] = { {10, 20, 30}, {40, 50, 60}, {70, 80, 90} }; int *pa; khi ®ã, ®Ó cã ®•îc kÕt qu¶ *pa = 50, c¸c lÖnh nµo sau ®©y lµ ®óng? a. pa = A + 4; Trang - 32 -
  33. LËp tr×nh h•íng ®èi t•îng b. pa = (*(A+1)) + 1; c. pa = &A[1][1]; d. pa = *((*(A+1)) + 1); 9. Gi¶ sö ta khai b¸o mét hµm cã sö dông con trá hµm víi khu«n mÉu nh• sau: int Calcul(int a, int b, int (*Xcalcul)(int x, int y)){}, vµ ta cã cµi ®Æt mét sè hµm nh• sau: int add(int a, int b); void cal(int a, int b); int squere(int a); khi ®ã, lêi gäi hµm nµo sau ®©y lµ ®óng: a. Calcul(5, 10, add); b. Calcul(5, 10, add(2, 3)); c. Calcul(5, 10, cal); d. Calcul(5, 10, squere); 10. Ta muèn cÊp ph¸t bé nhí cho mét con trá kiÓu int vµ khëi ®Çu gi¸ trÞ cho nã lµ 20. LÖnh nµo sau ®©y lµ ®óng: a. int *pa = 20; b. int *pa = new int{20}; c. int *pa = new int(20); d. int *pa = new int[20]; 11. Ta muèn cÊp ph¸t bé nhí cho mét m¶ng ®éng kiÓu int cã chiÒu dµi lµ 20. LÖnh nµo sau ®©y lµ ®óng: a. int *pa = 20; b. int *pa = new int{20}; c. int *pa = new int(20); d. int *pa = new int[20]; 12. XÐt ®o¹n ch•¬ng tr×nh sau: int A[5] = {10, 20, 30, 40, 50}; int *pa = A; pa = new int(2); khi ®ã, *pa = ? a. 10 b. 30 c. 2 d. Kh«ng x¸c ®Þnh Trang - 33 -
  34. LËp tr×nh h•íng ®èi t•îng 13. XÐt ®o¹n ch•¬ng tr×nh gåm 4 dßng lÖnh sau: int A[5] = {10, 20, 30, 40, 50}; int *pa = A; pa += 15; delete pa; §o¹n ch•¬ng tr×nh trªn cã lçi ë dßng nµo? a. 1 b. 2 c. 3 d. 4 14. ViÕt ch•¬ng tr×nh thùc hiÖn c¸c phÐp to¸n céng, trõ, nh©n, chia trªn ®a thøc. C¸c ®a thøc ®•îc biÓu diÔn b»ng m¶ng ®éng mét chiÒu. BËc cña ®a thøc vµ c¸c hÖ sè t•¬ng øng ®•îc nhËp tõ bµn phÝm. 15. ViÕt ch•¬ng tr×nh thùc hiÖn c¸c phÐp to¸n céng, trõ, nh©n hai ma trËn kÝch th•íc m*n. C¸c ma trËn ®•îc biÓu diÔn b»ng m¶ng ®éng hai chiÒu. Gi¸ trÞ kÝch cì ma trËn (m, n) vµ gi¸ trÞ c¸c phÇn tö cña ma trËn ®•îc nhËp tõ bµn phÝm. 16. §Ó ®Þnh nghÜa mét cÊu tróc sinh viªn cã tªn lµ Sinhvien, gåm cã tªn vµ tuæi sinh viªn. §Þnh nghÜa nµo sau ®©y lµ ®óng: a. struct Sinhvien { char name[20]; int age; }; b. struct { char name[20]; int age; } Sinh vien; c. typedef struct Sinhvien { char name[20]; int age; }; 17. Mét cÊu tróc ®•îc ®Þnh nghÜa nh• sau: struct Employee Trang - 34 -
  35. LËp tr×nh h•íng ®èi t•îng { char name[20]; int age; }; khi ®ã, c¸ch khai b¸o biÕn nµo sau ®©y lµ ®óng: a. struct Employee myEmployee; b. struct employee myEmployee; c. Employee myEmployee; d. employee myEmployee; 18. Mét cÊu tróc ®•îc ®Þnh nghÜa nh• sau: typedef struct employee { char name[20]; int age; } Employee; khi ®ã, c¸ch khai b¸o biÕn nµo sau ®©y lµ ®óng: a. Employee myEmployee; b. employee myEmployee; c. struct Employee myEmployee; d. struct employee myEmployee; 19. Víi cÊu tróc ®•îc ®Þnh nghÜa nh• trong bµi 3. Khi ®ã, c¸ch khëi t¹o biÕn nµo sau ®©y lµ ®óng: a. Employee myEmployee = {„A‟, 27}; b. Employee myEmployee = {“A”, 27}; c. Employee myEmployee = („A‟, 27); d. Employee myEmployee = (“A”, 27); 20. Víi cÊu tróc ®•îc ®Þnh nghÜa nh• trong bµi 3. Khi ®ã, c¸c c¸ch cÊp ph¸t bé nhí cho biÕn con trá nµo sau ®©y lµ ®óng: a. Employee *myEmployee = new Employee; b. Employee *myEmployee = new Employee(); c. Employee *myEmployee = new Employee(10); d. Employee *myEmployee = new Employee[10]; 21. §Þnh nghÜa mét cÊu tróc vÒ m«n häc cña mét häc sinh cã tªn Subject, bao gåm c¸c th«ng tin: • Tªn m«n häc, kiÓu char[]; Trang - 35 -
  36. LËp tr×nh h•íng ®èi t•îng • §iÓm tæng kÕt m«n häc, kiÓu float; 22. §Þnh nghÜa cÊu tróc vÒ häc sinh tªn lµ Student bao gåm c¸c th«ng tin sau: • Tªn häc sinh, kiÓu char[]; • Tuæi häc sinh, kiÓu int; • Líp häc sinh, kiÓu char[]; • Danh s¸ch ®iÓm c¸c m«n häc cña häc sinh, kiÓu lµ mét m¶ng c¸c cÊu tróc Subject ®· ®•îc ®Þnh nghÜa trong bµi tËp 21. • XÕp lo¹i häc lùc, kiÓu char[]; 23. Khai b¸o mét biÕn cã cÊu tróc lµ Student ®· ®Þnh nghÜa trong bµi 22. Sau ®ã, thùc hiÖn tÝnh ®iÓm trung b×nh cña tÊt c¶ c¸c m«n häc cña häc sinh ®ã, vµ viÕt mét thñ tôc xÕp lo¹i häcsinh dùa vµo ®iÓm trung b×nh c¸c m«n häc: • NÕu ®iÓm trung b×nh nhá h¬n 5.0, xÕp lo¹i kÐm • NÕu ®iÓm trung b×nh tõ 5.0 ®Õn d•íi 6.5, xÕp lo¹i trung b×nh. • NÕu ®iÓm trung b×nh tõ 6.5 ®Õn d•íi 8.0, xÕp lo¹i kh¸ • NÕu ®iÓm trung b×nh tõ 8.0 trë lªn, xÕp lo¹i giái. 24. ViÕt mét ch•¬ng tr×nh qu¶n lÝ c¸c häc sinh cña mét líp, lµ mét d·y c¸c cÊu tróc cã kiÓu Student ®Þnh nghÜa trong bµi 22. Sö dông thñ tôc ®· cµi ®Æt trong bµi 23 ®Ó thùc hiÖn c¸c thao t¸c sau: • Khëi t¹o danh s¸ch vµ ®iÓm cña c¸c häc sinh trong líp. • TÝnh ®iÓm trung b×nh vµ xÕp lo¹i cho tÊt c¶ c¸c häc sinh. • T×m tÊt c¶ c¸c häc sinh theo mét lo¹i nhÊt ®Þnh 25. ViÕt mét ch•¬ng tr×nh khai b¸o cÊu tróc ph©n sè, x©y dùng c¸c hµm vµ hµm to¸n tö ®Ó: a. NhËp mét ph©n sè tõ bµn phÝm b. HiÓn thÞ mét ph©n sè ra mµn h×nh c. Rót gän mét ph©n sè ®Õn d¹ng ph©n sè tèi gi¶n d. TÝnh tæng hai ph©n sè e. TÝnh hiÖu hai ph©n sè f. TÝnh tÝch hai ph©n sè g. TÝnh th•¬ng hai ph©n sè 26. ViÕt mét ch•¬ng tr×nh khai b¸o cÊu tróc sè phøc, x©y dùng c¸c hµm vµ hµm to¸n tö ®Ó: a. NhËp mét sè phøc tõ bµn phÝm b. HiÓn thÞ mét sè phøc ra mµn h×nh Trang - 36 -
  37. LËp tr×nh h•íng ®èi t•îng c. TÝnh tæng hai sè phøc d. TÝnh hiÖu hai sè phøc e. TÝnh tÝch hai sè phøc f. TÝnh th•¬ng hai sè phøc 27. ViÕt mét ch•¬ng tr×nh khai b¸o cÊu tróc Stack, x©y dùng c¸c hµm ®Ó: a. Khëi t¹o Stack rçng b. KiÓm tra Stack ®Çy c. KiÓm tra Stack rçng c. Bæ sung mét phÇn tö vµo Stack d. Lo¹i bá phÇn tö ë ®Ønh Stack Sö dông Stack ®Ó ®æi mét sè nguyªn d•¬ng tõ hÖ thËp ph©n sang hÖ nhÞ ph©n 28. ViÕt mét ch•¬ng tr×nh khai b¸o cÊu tróc ma trËn vu«ng cÊp n, x©y dùng c¸c hµm vµ hµm to¸n tö ®Ó: a. NhËp mét ma trËn tõ bµn phÝm b. HiÓn thÞ mét ma trËn ra mµn h×nh c. TÝnh tæng hai ma trËn d. TÝnh hiÖu hai ma trËn e. TÝnh tÝch hai ma trËn f. T×m ma trËn chuyÓn vÞ 29. ViÕt ch•¬ng tr×nh khai b¸o cÊu tróc mét nót (phÇn tö) trong danh s¸ch nèi ®¬n cã tr•êng info cã kiÓu sè nguyªn vµ x©y dùng c¸c hµm ®Ó: a. T¹o danh s¸ch b. HiÓn thÞ danh s¸ch c. Bæ sung mét phÇn tö vµo cuèi danh s¸ch d. Lo¹i bá phÇn tö ë ®Çu danh s¸ch e. S¾p xÕp c¸c phÇn tö cña danh s¸ch theo thø tù t¨ng dÇn cña gi¸ trÞ tr•êng info f. T×m phÇn tö cã gi¸ trÞ tr•êng info lín nhÊt g. T×m phÇn tö cã gi¸ trÞ tr•êng info b»ng x cho tr•íc 30. ViÕt mét ch•¬ng tr×nh khai b¸o cÊu mét nót (phÇn tö) trong danh s¸ch nèi kÐp cã tr•êng info cã kiÓu student ®Þnh nghÜa trong bµi 22 vµ c¸c hµm ®Ó: a. T¹o danh s¸ch l•u tr÷ danh s¸ch sinh viªn b. HiÓn thÞ danh s¸ch c. Bæ sung mét phÇn tö vµo cuèi danh s¸ch(nót cùc ph¶i) d. Lo¹i bá phÇn tö ë ®Çu danh s¸ch(nót cùc tr¸i) Trang - 37 -
  38. LËp tr×nh h•íng ®èi t•îng e. S¾p xÕp c¸c phÇn tö cña danh s¸ch theo thø tù tõ tr¸i sang ph¶i gi¸ trÞ tr•êng tuæi sinh viªn t¨ng dÇn f. T×m phÇn tö cã gi¸ trÞ tr•êng tªn sinh viªn ®•îc nhËp tõ bµn phÝm. Trang - 38 -
  39. LËp tr×nh h•íng ®èi t•îng Ch•¬ng 2: Líp vµ ®èi t•îng Néi dung cña ch•¬ng tËp trung tr×nh bµy c¸c vÊn ®Ò sau: Líp: ®Þnh nghÜa líp, thµnh phÇn cña líp, ph¹m vi truy xuÊt ®Õn c¸c thµnh phÇn cña líp. §èi t•îng: biÕn, m¶ng, con trá ®èi t•îng. Hµm, hµm b¹n vµ c¸c ph•¬ng thøc cña líp. 2.1. §Þnh nghÜa líp Líp lµ mét kiÓu d÷ liÖu do ng•êi dïng tù ®Þnh nghÜa theo có ph¸p: class { private: public: }; Trong ®ã: c¸c thµnh phÇn cña líp bao gåm c¸c thuéc tÝnh vµ c¸c ph•¬ng thøc. Mçi thuéc tÝnh ®•îc khai b¸o gièng có ph¸p khai b¸o biÕn, mçi ph•¬ng thøc ®•îc khai b¸o gièng khai b¸o hµm. VÝ dô 2.1: #include #include class point { /*khai b¸o c¸c thµnh phÇn d÷ liÖu riªng*/ private: int x,y; /*khai b¸o c¸c ph•¬ng thøc c«ng céng*/ public: void init(int ox, int oy); void move(int dx, int dy); void display(); Trang - 39 -
  40. LËp tr×nh h•íng ®èi t•îng }; /*®Þnh nghÜa c¸c ph•¬ng thøc bªn ngoµi khai b¸o líp*/ void point::init(int ox, int oy) { cout<<"Ham thanh phan init\n"; x = ox; y = oy; /*x,y lµ c¸c thµnh phÇn cña ®èi t•îng gäi ph•¬ng thøc*/ } void point::move(int dx, int dy) { cout<<"Ham thanh phan move\n"; x += dx; y += dy; } void point::display() { cout<<"Ham thanh phan display\n"; cout<<"Toa do: "<<x<<" "<<y<<"\n"; } void main() { clrscr(); point p; p.init(2,4); /*gäi ph•¬ng thøc tõ ®èi t•îng*/ p.display(); p.move(1,2); p.display(); getch(); } 2.2. Ph¹m vi truy xuÊt Khi khai b¸o c¸c thµnh phÇn cña líp ta sö dông c¸c tõ kho¸ private, protected, public ®Ó quy ®Þnh ph¹m vi truy xuÊt ®Õn c¸c thµnh phÇn nµy. C¸c thµnh phÇn private chØ ®•îc phÐp truy xuÊt trong ph¹m vi líp mµ nã ®•îc khai b¸o, c¸c thµnh phÇn protected ®•îc phÐp truy xuÊt trong ph¹m vi líp nã ®•îc khai b¸o vµ trong líp dÉn xuÊt trùc tiÕp (líp con) tõ líp ®ã, c¸c thµnh phÇn public cã ph¹m vi truy xuÊt trong toµn bé ch•¬ng tr×nh. Trang - 40 -
  41. LËp tr×nh h•íng ®èi t•îng C¸c ph•¬ng thøc cña líp cã thÓ ®•îc ®Þnh nghÜa bªn trong ®Þnh nghÜa líp hoÆc bªn ngoµi ®Þnh nghÜa líp. Khi ®Þnh nghÜa mét ph•¬ng thøc bªn ngoµi ®Þnh nghÜa líp th× tr•íc tªn ph•¬ng thøc ta sö dông Tªn_líp :: (Hai dÊu hai chÊm ®•îc gäi lµ to¸n tö ph¹m vi, nã x¸c ®Þnh ph•¬ng thøc ®ang ®•îc ®Þnh nghÜa lµ thµnh phÇn cña líp nµo). VÝ dô 2.2: §Þnh nghÜa ph•¬ng thøc display ë bªn ngoµi ®Þnh nghÜa líp point void point::display() { cout<<"Ham thanh phan display\n"; cout<<"Toa do: "<<x<<" "<<y<<"\n"; } 2.3. §èi t•îng §èi t•îng lµ mét kh¸i niÖm trong lËp tr×nh h•íng ®èi t•îng biÓu thÞ sù liªn kÕt gi÷a d÷ liÖu vµ c¸c hµm (gäi lµ c¸c ph•¬ng thøc) thao t¸c trªn d÷ liÖu ®ã. Ta cã c«ng thøc sau: §èi t•îng = D÷ liÖu + Ph•¬ng thøc §èi t•îng chÝnh lµ c«ng cô hç trî cho sù ®ãng gãi. Sù ®ãng gãi lµ c¬ chÕ liªn kÕt c¸c lÖnh thao t¸c vµ d÷ liÖu cã liªn quan, gióp cho c¶ hai ®•îc an toµn tr¸nh ®•îc sù can thiÖp tõ bªn ngoµi vµ viÖc sö dông sai. 2.3.1. BiÕn, m¶ng ®èi t•îng Trong C++, mét ®èi t•îng cã thÓ ®•îc x¸c lËp th«ng quan mét biÕn cã kiÓu líp. Mét biÕn ®èi t•îng ®•îc khai b¸o theo có ph¸p: Tªn_líp Tªn_biÕn; VÝ dô: point A; §Ó truy nhËp vµo thµnh phÇn cña ®èi t•îng th«ng qua biÕn ®èi t•îng, ta sö dông có ph¸p: Tªn_biÕn.Tªn_thµnh_phÇn; VÝ dô: A.x //truy nhËp thuéc tÝnh A.display(); //truy nhËp ph•¬ng thøc M¶ng ®èi t•îng ®•îc khai b¸o nh• m¶ng th«ng th•êng, chØ cã ®iÒu kiÓu d÷ liÖu ë ®©y lµ mét líp. Khi ®ã, mçi phÇn tö m¶ng lµ mét ®èi t•îng. VÝ dô point mang[100]; Trang - 41 -
  42. LËp tr×nh h•íng ®èi t•îng §Ó truy nhËp vµo thµnh phÇn cña ®èi t•îng th«ng qua m¶ng ®èi t•îng, ta sö dông có ph¸p: Tªn_biÕn_m¶ng[chØ sè phÇn tö].Tªn_thµnh_phÇn; VÝ dô: mang[4].x //truy nhËp thuéc tÝnh mang[4].display(); //truy nhËp ph•¬ng thøc 2.3.2. Con trá ®èi t•îng Con trá ®èi t•îng ®•îc dïng ®Ó chøa ®Þa chØ cña biÕn, m¶ng ®èi t•îng. Nã ®•îc khai b¸o theo có ph¸p: Tªn_líp *Con_trá; VÝ dô: point *p; §Ó truy nhËp vµo thµnh phÇn cña ®èi t•îng th«ng qua con trá ®èi t•îng, ta sö dông có ph¸p: Con_tro->Tªn_thµnh_phÇn; VÝ dô: p->x //truy nhËp thuéc tÝnh p->display(); //truy nhËp ph•¬ng thøc 2.3.3. §èi cña ph•¬ng thøc, con trá this Con trá this lµ ®èi thø nhÊt cña ph•¬ng thøc, chÝnh v× thÕ so víi hµm tù do thùc hiÖn cïng chøc n¨ng, ph•¬ng thøc cña líp bao giê còng cã Ýt h¬n hµm mét ®èi kiÓu con trá ®èi t•îng cña líp. §èi nµy sÏ ®•îc x¸c ®Þnh trong lêi gäi ph•¬ng thøc ®ã. Khi truy nhËp vµo c¸c thuéc tÝnh vµ ph•¬ng thøc cña líp cã thÓ viÕt: this->tªn_thuéc_tÝnh hoÆc chØ cÇn viÕt tªn_thuéc_tÝnh. VÝ dô 2.3: #include #include class point { private: int x,y; public: void nhap(); void hienthi(); }; void point::nhap(); { cout >this->x; //sö dông this cout >this->y; //sö dông this Trang - 42 -
  43. LËp tr×nh h•íng ®èi t•îng } void point::hienthi(); { cout<<”Toa do cua diem la: (“<<x<<”,”<<y<<”)”; //kh«ng sö dông this } void main() { clrscr(); point p; p.nhap(); //lêi gäi ph•¬ng thøc p.hienthi(); getch(); } 2.4. Hµm vµ c¸c ph•¬ng thøc cña líp 2.4.1. Hµm vµ hµm b¹n Hµm Hµm cã tÝnh chÊt sau: Ph¹m vi ho¹t ®éng cña hµm lµ trong toµn bé ch•¬ng tr×nh. Tøc lµ, hµm cã thÓ ®•îc gäi bÊt kú chç nµo trong ch•¬ng tr×nh. §èi (tham sè) cña hµm cã thÓ lµ c¸c ®èi t•îng. Tuy nhiªn, trong th©n cña hµm kh«ng thÓ truy nhËp vµo c¸c thuéc tÝnh riªng (private, protected) cña ®èi t•îng nµy. Hµm b¹n Hµm b¹n cã tÝnh chÊt sau: Ph¹m vi ho¹t ®éng cña hµm b¹n lµ trong toµn bé ch•¬ng tr×nh. Tøc lµ, hµm b¹n cã thÓ ®•îc gäi bÊt kú chç nµo trong ch•¬ng tr×nh. §èi (tham sè) cña hµm b¹n cã thÓ lµ c¸c ®èi t•îng. Tuy nhiªn, trong th©n cña hµm b¹n cña mét líp ®•îc phÐp truy nhËp vµo c¸c thuéc tÝnh cña ®èi t•îng cña líp nµy. Lêi gäi hµm b¹n gièng lêi gäi cña hµm th«ng th•êng Hµm b¹n cña mét líp kh«ng ph¶i lµ ph•¬ng thøc cña líp nªn kh«ng cã ®èi ngÇm ®Þnh lµ con trá this nh• ph•¬ng thøc cña líp Trang - 43 -
  44. LËp tr×nh h•íng ®èi t•îng Mét hµm cã thÓ trë thµnh hµm b¹n cña nhiÒu líp. Khi ®ã, hµm nµy cã thÓ truy nhËp vµo tÊt c¶ c¸c thuéc tÝnh cña c¸c ®èi t•îng cña líp mµ nã lµ b¹n. §Ó mét hµm trë thµnh hµm b¹n cña mét líp cã 2 c¸ch viÕt: C¸ch 1: Dïng tõ kho¸ friend ®Ó khai b¸o hµm trong khai b¸o líp vµ x©y dùng hµm bªn ngoµi líp nh• c¸c hµm th«ng th•êng. MÉu có ph¸p nh• sau: class A { private: //khai b¸o c¸c thµnh phÇn riªng public: //khai b¸o c¸c thµnh phÇn dïng chung friend KiÓu_tr¶_vÒ Tªn_hµm_b¹n(Danh s¸ch tham sè); }; //X©y dùng hµm bªn ngoµi khai b¸o líp KiÓu_tr¶_vÒ Tªn_hµm_b¹n( Danh s¸ch tham sè) { // Th©n cña hµm b¹n } C¸ch 2: Dïng tõ kho¸ friend ®Ó x©y dùng hµm ngay bªn trong khai b¸o líp. MÉu có ph¸p: class A { private: //khai b¸o c¸c thµnh phÇn riªng public: //khai b¸o c¸c thµnh phÇn dïng chung //X©y dùng hµm bªn trong khai b¸o líp friend KiÓu_tr¶_vÒ Tªn_hµm_b¹n( Danh s¸ch tham sè) { // Th©n cña hµm b¹n } }; Trang - 44 -
  45. LËp tr×nh h•íng ®èi t•îng Cã nhiÒu kiÓu b¹n bÌ: - Hµm tù do lµ b¹n cña mét líp. - Hµm thµnh phÇn cña mét líp lµ b¹n cña mét líp kh¸c. - Hµm b¹n cña nhiÒu líp. - TÊt c¶ c¸c hµm thµnh phÇn cña mét líp lµ b¹n cña mét líp kh¸c. Hµm tù do b¹n cña mét líp Trong hµm b¹n, kh«ng cßn tham sè ngÇm ®Þnh this nh• trong hµm thµnh phÇn. Hµm b¹n cña mét líp cã thÓ cã mét hay nhiÒu tham sè, hoÆc cã gi¸ trÞ tr¶ vÒ thuéc kiÓu líp ®ã. Hµm thµnh phÇn cña líp lµ b¹n cña líp kh¸c Gi¶ thiÕt cã hai líp A vµ B, trong B cã mét hµm thµnh phÇn f khai b¸o nh• sau: int f(char , A); NÕu f cã nhu cÇu truy xuÊt vµo c¸c thµnh phÇn riªng cña A th× f cÇn ph¶i ®•îc khai b¸o lµ b¹n cña A ë trong líp A b»ng c©u lÖnh: friend int B::f(char , A); §Ó biªn dÞch ®•îc c¸c khai b¸o cña líp A cã chøa khai b¸o b¹n bÌ kiÓu nh•: friend int B::f(char, A); ch•¬ng tr×nh dÞch cÇn ph¶i biÕt ®•îc néi dung cña líp B; nghÜa lµ khai b¸o cña B (kh«ng nhÊt thiÕt ®Þnh nghÜa cña c¸c hµm thµnh phÇn) ph¶i ®•îc biªn dÞch tr•íc khai b¸o cña A. Ng•îc l¹i, khi biªn dÞch khai b¸o: int f(char, A) ; bªn trong líp B, ch•¬ng tr×nh dÞch kh«ng nhÊt thiÕt ph¶i biÕt chi tiÕt néi dung cña A, nã chØ cÇn biÕt r»ng A lµ mét líp. §Ó cã ®•îc ®iÒu nµy ta dïng chØ thÞ sau: class A; tr•íc khai b¸o líp B. ViÖc biªn dÞch ®Þnh nghÜa hµm f cÇn c¸c th«ng tin ®Çy ®ñ vÒ c¸c thµnh phÇn cña A vµ B; nh• vËy c¸c khai b¸o cña A vµ B ph¶i cã tr•íc ®Þnh nghÜa ®Çy ®ñ cña f. Tãm l¹i, s¬ ®å khai b¸o vµ ®Þnh nghÜa ph¶i nh• sau: class A; class B { int f(char, A); }; class A Trang - 45 -
  46. LËp tr×nh h•íng ®èi t•îng { friend int B::f(char, A); }; int B::f(char ,A ) { } Hµm b¹n cña nhiÒu líp Mäi hµm (hµm tù do hay hµm thµnh phÇn) ®Òu cã thÓ lµ b¹n cña nhiÒu líp kh¸c nhau. Sau ®©y lµ mét vÝ dô mét hµm lµ b¹n cña hai líp A vµ B. class B; class A { friend void f(A, B); }; class B { friend void f(A,B); }; void f(A ,B ) { //truy nhËp vµo c¸c thµnh phÇn riªng cña hai líp bÊt kú A vµ B } TÊt c¶ c¸c hµm cña líp lµ b¹n cña líp kh¸c Khi tÊt c¶ c¸c hµm thµnh phÇn cña mét líp lµ hµm b¹n cña mét líp kh¸c ta cã kh¸i niÖm líp b¹n, Ch¼ng h¹n, tÊt c¶ c¸c hµm thµnh phÇn cña líp B lµ b¹n cña líp A th× khai b¸o trong líp A chØ thÞ: friend class B; Trang - 46 -
  47. LËp tr×nh h•íng ®èi t•îng thay v× ph¶i khai b¸o tiªu ®Ò cña c¸c hµm b¹n lµ hµm thµnh phÇn cña líp B. class A { friend class B; }; VÝ dô 2.4: Ch•¬ng tr×nh minh ho¹ viÖc sö dông hµm b¹n #include #include int uscln(int a, int b) { while(a!=b) if(a>b) a=a-b; else b=b-a; return a; } class phanso { private: int ts; int ms; public: void nhap() { cout >ts; cout >ms; } void hienthi(); friend phanso rutgon(phanso x)//hµm b¹n { phanso kq; kq.ts=x.ts/uscln(x.ts,x.ms); kq.ms=x.ms/uscln(x.ts,x.ms); Trang - 47 -
  48. LËp tr×nh h•íng ®èi t•îng return kq; } phanso operator+(phanso x); phanso operator-(phanso x); phanso operator*(phanso x); phanso operator/(phanso x); }; void phanso::hienthi() { cout<<ts<<"/"<<ms; } phanso phanso::operator+(phanso x) { phanso kq; kq.ts=ts*x.ms+ms*x.ts; kq.ms=ms*x.ms; return kq; } phanso phanso::operator-(phanso x) { phanso kq; kq.ts=ts*x.ms-ms*x.ts; kq.ms=ms*x.ms; return kq; } phanso phanso::operator*(phanso x) { phanso kq; kq.ts=ts*x.ts; kq.ms=ms*x.ms; return kq; } phanso phanso::operator/(phanso x) { phanso kq; Trang - 48 -
  49. LËp tr×nh h•íng ®èi t•îng kq.ts=ts*x.ms; kq.ms=ms*x.ts; return kq; } void main() { phanso x,y,z,t; cout<<"Nhap phan so thu nhat\n"; x.nhap(); cout<<"Nhap phan so thu hai\n"; y.nhap(); cout<<"\nTong hai phan so:"; z=x+y; t=rutgon(z); t.hienthi(); cout<<"\nHieu hai phan so:"; z=x-y; t=rutgon(z); t.hienthi(); cout<<"\nTich hai phan so:"; z=x*y; t=rutgon(z); t.hienthi(); cout<<"\nThuong hai phan so:"; z=x/y; t=rutgon(z); t.hienthi(); getch(); } 2.4.2. Ph•¬ng thøc to¸n tö Trong C++, cã thÓ ®Þnh nghÜa chång ®èi víi hÇu hÕt c¸c phÐp to¸n (mét ng«i hoÆc hai ng«i) trªn c¸c líp, nghÜa lµ mét trong sè c¸c to¸n h¹ng tham gia phÐp to¸n lµ c¸c ®èi t•îng. §©y lµ mét kh¶ n¨ng m¹nh v× nã cho phÐp x©y dùng trªn c¸c líp c¸c to¸n tö cÇn thiÕt, lµm cho ch•¬ng tr×nh ®•îc viÕt ng¾n gän dÔ ®äc h¬n vµ cã ý Trang - 49 -
  50. LËp tr×nh h•íng ®èi t•îng nghÜa h¬n. Ch¼ng h¹n, khi ®Þnh nghÜa mét líp sp ®Ó biÓu diÔn c¸c sè phøc, cã thÓ viÕt trong C++: a+b, a-b, a*b, a/b víi a, b lµ c¸c ®èi t•îng sp. §Ó cã ®•îc ®iÒu nµy, ta ®Þnh nghÜa chång c¸c phÐp to¸n +, -, * vµ / b»ng c¸ch ®Þnh nghÜa c¸c ph•¬ng thøc to¸n tö gièng nh• ®Þnh nghÜa mét ph•¬ng thøc th«ng th•êng kh¸c cña líp, chØ kh¸c lµ ®©y lµ ph•¬ng thøc to¸n tö. V× vËy, tªn cña ph•¬ng thøc ®•îc ®Æt b»ng c¸ch ghÐp tõ kho¸ operator vµ ký hiÖu cña phÐp to¸n t•¬ng øng (gièng c¸ch ®Æt tªn hµm to¸n tö). VÝ dô 2.5: #include #include class sp { int pt,pa; public: void nhap(); void ht() { cout.precision(2); if(pa>=0) cout >pt; cout >pa; } sp::operator+(sp x) { sp z; Trang - 50 -
  51. LËp tr×nh h•íng ®èi t•îng z.pt=x.pt+pt; z.pa=x.pa+pa; return z; } sp::operator-(sp x) { sp z; z.pt=x.pt-pt; z.pa=x.pa-pa; return z; } sp::operator*(sp x) { sp z; z.pt=x.pt*pt-x.pa*pa; z.pa=x.pt*pa+x.pa*pt; return z; } sp::operator/(sp x) { sp z; z.pt=(x.pt*pt+x.pa*pa)/(x.pt*x.pt+pt*pt); z.pa=(x.pt*pa-x.pa*pt)/(x.pt*x.pt+pt*pt); return z; } void main() { sp a,b,c; cout<<"\nNhap so phuc thu nhat\n"; a.nhap(); cout<<"\nNhap so phuc thu hai\n"; b.nhap(); c = a+b cout<<"Tong hai so phuc:"; c.ht(); c= a- b; Trang - 51 -
  52. LËp tr×nh h•íng ®èi t•îng cout > dïng víi cout vµ cin ph¶i ®•îc ®Þnh nghÜa nh• hµm b¹n. - hai phÐp to¸n ++ vµ cã thÓ sö dông theo hai c¸ch kh¸c nhau øng víi d¹ng tiÒn tè ++a, b vµ d¹ng hËu tè a++, b . §iÒu nµy ®ßi hái hai hµm to¸n tö kh¸c nhau. C¸c to¸n tö ®•îc ®Þnh nghÜa chång ph¶i b¶o toµn sè ng«i cña chÝnh to¸n tö ®ã theo c¸ch hiÓu th«ng th•êng, vÝ dô: cã thÓ ®Þnh nghÜa to¸n tö “-” mét ng«i vµ hai ng«i trªn líp t•¬ng øng víi phÐp ®¶o dÊu (mét ng«i) vµ phÐp trõ sè häc (hai ng«i), nh•ng kh«ng thÓ ®Þnh nghÜa to¸n tö g¸n mét ng«i, cßn ++ l¹i cho hai ng«i. NÕu lµm vËy, ch•¬ng tr×nh dÞch sÏ hiÓu lµ t¹o ra mét ký hiÖu phÐp to¸n míi. Khi ®Þnh nghÜa chång to¸n tö, ph¶i tu©n theo nguyªn t¾c lµ Mét trong sè c¸c to¸n h¹ng ph¶i lµ ®èi t•îng. Nãi c¸ch kh¸c, ph•¬ng thøc to¸n tö ph¶i hoÆc lµ ph•¬ng thøc hoÆc lµ mét hµm tù do. Khi ®ã, ph•¬ng thøc ®· cã mét tham sè ngÇm ®Þnh cã kiÓu líp chÝnh lµ ®èi t•îng gäi ph•¬ng thøc. Tham sè ngÇm ®Þnh nµy ®ãng vai trß to¸n h¹ng ®Çu tiªn(®èi víi phÐp to¸n hai ng«i) hay to¸n h¹ng duy nhÊt (®èi víi phÐp to¸n mét ng«i). Do vËy, nÕu to¸n tö lµ mét ng«i th× ph•¬ng thøc to¸n tö thµnh phÇn sÏ kh«ng chøa mét tham sè nµo kh¸c. Ng•îc l¹i khi to¸n tö lµ hai ng«i, ph•¬ng thøc to¸n tö sÏ cã thªm mét ®èi sè t•êng minh, . Trong tr•êng hîp nµy, Ýt nhÊt tham sè thø nhÊt hoÆc tham sè thø hai (nÕu cã) ph¶i cã kiÓu líp. H¬n n÷a, mçi hµm to¸n tö chØ cã thÓ ¸p dông víi kiÓu to¸n h¹ng nhÊt ®Þnh; cÇn chó ý r»ng c¸c tÝnh chÊt vèn cã, ch¼ng h¹n tÝnh giao ho¸n cña to¸n tö kh«ng thÓ ¸p dông mét c¸ch tuú tiÖn cho c¸c to¸n tö ®•îc ®Þnh nghÜa chång. Kh«ng nªn ®Þnh nghÜa nh÷ng hµm hµm to¸n tö kh¸c nhau cïng lµm nh÷ng c«ng viÖc gièng nhau v× dÔ x¶y ra nhËp nh»ng. Ch¼ng h¹n, ®· cã mét ph•¬ng thøc operator+ cã tham sè lµ Trang - 52 -
  53. LËp tr×nh h•íng ®èi t•îng ®èi t•îng sp th× kh«ng ®•îc ®Þnh nghÜa thªm mét hµm operator+ lµ mét hµm tù do cã hai tham sè lµ ®èi t•îng sp. Quy t¾c sö dông ph•¬ng thøc to¸n tö VÒ nguyªn t¾c, ®Þnh nghÜa chång mét phÐp to¸n lµ kh¸ ®¬n gi¶n, nh•ng viÖc sö dông phÐp to¸n ®Þnh nghÜa chång l¹i kh«ng ph¶i dÔ dµng vµ ®ßi hái ph¶i c©n nh¾c bëi lÏ nÕu bÞ l¹m dông sÏ lµm cho ch•¬ng tr×nh khã hiÓu. Ph¶i lµm sao ®Ó c¸c phÐp to¸n vÉn gi÷ ®•îc ý nghÜa trùc quan nguyªn thuû cña chóng. Ch¼ng h¹n kh«ng thÓ ®Þnh nghÜa céng “+” nh• phÐp trõ “-” hai gi¸ trÞ. Ph¶i x¸c ®Þnh tr•íc ý nghÜa c¸c phÐp to¸n tr•íc khi viÕt ®Þnh nghÜa cña c¸c hµm to¸n tö t•¬ng øng. C¸c phÐp to¸n mét ng«i lµ: *, &, ~, !, ++, , sizeof (kiÓu) C¸c hµm to¸n tö t•¬ng øng chØ cã mét ®èi sè vµ ph¶i tr¶ vÒ gi¸ trÞ cïng kiÓu víi to¸n h¹ng, riªng sizeof cã gi¸ trÞ tr¶ vÒ kiÓu nguyªn kh«ng dÊu vµ to¸n tö (kiÓu) dïng ®Ó tr¶ vÒ mét gi¸ trÞ cã kiÓu nh• ®· ghi trong dÊu ngoÆc. C¸c phÐp to¸n hai ng«i nh•: *,/,%,+,-, >, , =,==,!=,&,|,^,&&,|| Hai to¸n h¹ng tham gia c¸c phÐp to¸n kh«ng nhÊt thiÕt ph¶i cïng kiÓu, mÆc dï trong thùc tÕ sö dông th× th•êng lµ vËy. Nh• vËy chØ cÇn mét trong hai ®èi sè cña hµm to¸n tö t•¬ng øng lµ ®èi t•îng lµ ®ñ. C¸c to¸n tö g¸n gåm cã: =,+=,-=,*=,/=,%=,>>=, ” PhÐp to¸n nµy ®•îc dïng ®Ó truy xuÊt c¸c thµnh phÇn cña mét cÊu tróc hay mét líp vµ cÇn ph©n biÖt víi nh÷ng c¸ch sö dông kh¸c ®Ó tr¸nh dÉn ®Õn sù nhÇm lÉn. Cã thÓ ®Þnh nghÜa phÐp to¸n lÊy thµnh phÇn gièng nh• ®èi víi c¸c phÐp to¸n mét ng«i. To¸n tö truy nhËp thµnh phÇn theo chØ sè To¸n tö lÊy thµnh phÇn theo chØ sè ®•îc dïng ®Ó x¸c ®Þnh mét thµnh phÇn cô thÓ trong mét khèi d÷ liÖu (cÊp ph¸t ®éng hay tÜnh). Th«ng th•êng phÐp to¸n nµy ®•îc dïng víi m¶ng, nh•ng còng cã thÓ ®Þnh nghÜa l¹i nã khi lµm viÖc víi c¸c kiÓu d÷ liÖu kh¸c. Ch¼ng h¹n víi kiÓu d÷ liÖu vector cã thÓ ®Þnh nghÜa phÐp lÊy theo chØ sè ®Ó tr¶ vÒ mét thµnh phÇn to¹ ®é nµo ®ã cña vector vµ ph¶i ®•îc ®Þnh nghÜa nh• ph•¬ng thøc cã mét ®èi sè t•êng minh. Trang - 53 -
  54. LËp tr×nh h•íng ®èi t•îng 2.4.3. Hµm t¹o Hµm t¹o lµ mét ph•¬ng thøc ®Æc biÖt kh«ng thÓ thiÕu ®•îc trong mét líp. Nã ®•îc gäi tù ®éng mçi khi cã mét ®èi t•îng ®•îc khai b¸o. Chøc n¨ng cña hµm t¹o lµ khëi t¹o c¸c gi¸ trÞ thµnh phÇn d÷ liÖu cña ®èi t•îng, xin cÊp ph¸t bé nhí cho c¸c thµnh phÇn d÷ liÖu ®éng. Mét sè ®Æc ®iÓm quan träng cña hµm t¹o: - Hµm t¹o cã cïng tªn víi tªn cña líp. - Hµm t¹o ph¶i cã thuéc tÝnh public. - Hµm t¹o kh«ng cã gi¸ trÞ tr¶ vÒ v× thÕ kh«ng cÇn khai b¸o kiÓu gi¸ trÞ tr¶ vÒ cña hµm - Cã thÓ cã nhiÒu hµm t¹o trong cïng líp (chång c¸c hµm t¹o). Khi mét líp cã nhiÒu hµm t¹o, viÖc t¹o c¸c ®èi t•îng ph¶i kÌm theo c¸c tham sè phï hîp víi mét trong c¸c hµm t¹o ®· khai b¸o. VÝ dô 2.6: class point { int x,y; public: point() {x=0;y=0;} point(int ox, int oy) {x=ox;y=oy;} /*hµm t¹o cã hai tham sè*/ void move(int,int); void display(); }; point a(1); /* Lçi v× tham sè kh«ng phï hîp víi hµm t¹o */ point b;/*§óng, tham sè phï hîp víi hµm t¹o kh«ng tham sè*/ point c(2,3);/*§óng, tham sè phï hîp víi hµm t¹o thø hai, cã hai tham sè*/ Hµm t¹o cã thÓ ®•îc khai b¸o víi c¸c tham sè cã gi¸ trÞ ngÇm ®Þnh. XÐt vÝ dô sau: /*§Þnh nghÜa l¹i líp point*/ class point { int x,y; public: point(int ox, int oy = 0) {x=ox; y=oy;} /*hµm t¹o cã hai tham sè*/ void move(int,int); Trang - 54 -
  55. LËp tr×nh h•íng ®èi t•îng void display(); }; point a; /*Lçi: kh«ng cã hµm t¹o ngÇm ®Þnh hoÆc hµm t¹o víi c¸c tham sè cã gi¸ trÞ ngÇm ®Þnh*/ point b(1);//§èi sè thø hai nhËn gi¸ trÞ 0 point c(2,3);//§óng 2.4.4. Líp kh«ng cã hµm t¹o vµ hµm t¹o mÆc ®Þnh Hµm t¹o ngÇm ®Þnh do ch•¬ng tr×nh dÞch cung cÊp khi trong khai b¸o líp kh«ng cã ®Þnh nghÜa hµm t¹o nµo. DÜ nhiªn hµm t¹o ngÇm ®Þnh ®ã kh«ng thùc hiÖn bÊt cø nhiÖm vô nµo ngoµi viÖc “lÊp chç trèng”. §«i khi ng•êi ta còng gäi hµm t¹o kh«ng cã tham sè do ng•êi sö dông ®Þnh nghÜa lµ hµm t¹o ngÇm ®Þnh. CÇn ph¶i cã hµm t¹o ngÇm ®Þnh khi cÇn khai b¸o m¶ng c¸c ®èi t•îng. VÝ dô, trong khai b¸o: X a[10]; b¾t buéc trong líp X ph¶i cã mét hµm t¹o ngÇm ®Þnh. Ta minh ho¹ nhËn xÐt nµy b»ng hai vÝ dô sau: a. Trong tr•êng hîp thø nhÊt kh«ng dïng hµm t¹o kh«ng tham sè: VÝ dô 2.7: #include class point { int x; int y; public: point(int ox,int oy) {x=ox; y=oy;} void move(int dx,int dy) ; void display(); }; void point::move(int dx, int dy) { x+=dx; y+=dy; } void point::display() { Trang - 55 -
  56. LËp tr×nh h•íng ®èi t•îng cout class point { int x; int y; public: point(int ox,int oy) {x=ox; y=oy;} point() {x= 0; y = 0;}//khai b¸o thªm hµm t¹o kh«ng cã tham sè void move(int dx,int dy) ; void display(); }; void point::move(int dx, int dy) { x+=dx; y+=dy; } void point::display() { Trang - 56 -
  57. LËp tr×nh h•íng ®èi t•îng cout class point { int x; int y; public: point(int ox = 0,int oy = 0) {x=ox; y=oy;} void move(int dx,int dy) ; void display(); }; void point::move(int dx, int dy) { x+=dx; y+=dy; } void point::display() { cout<<“Toa do : “<<x<<" "<<y<<"\n"; } Trang - 57 -
  58. LËp tr×nh h•íng ®èi t•îng void main() { clrscr(); point a(5,2); //Hîp lÖ a.display(); a.move(-2,4); a.display(); point b[10]; //Hîp lÖ getch(); } 2.4.5. Hµm t¹o sao chÐp XÐt c¸c c©u lÖnh khai b¸o vµ khëi t¹o gi¸ trÞ cho mét biÕn nguyªn: int p; int x = p; C©u lÖnh thø hai khai b¸o mét biÕn nguyªn x vµ g¸n cho nã gi¸ trÞ cña biÕn nguyªn p. T•¬ng tù, ta còng cã thÓ khai b¸o mét ®èi t•îng vµ g¸n cho nã néi dung cña mét ®èi t•îng cïng líp ®· tån t¹i tr•íc ®ã. Ch¼ng h¹n: point p(2,3);/*gi¶ thiÕt líp point cã hµm t¹o hai tham sè*/ point q =p; DÜ nhiªn hai ®èi t•îng, míi q vµ cò p cã cïng néi dung. Khi mét ®èi t•îng ®•îc t¹o ra (khai b¸o) th× mét hµm t¹o cña líp t•¬ng øng sÏ ®•îc gäi. Hµm t¹o ®•îc gäi khi khai b¸o vµ khëi t¹o néi dung mét ®èi t•îng th«ng qua mét ®èi t•îng kh¸c, gäi lµ hµm t¹o sao chÐp. NhiÖm vô cña hµm t¹o sao chÐp lµ t¹o ra mét ®èi t•îng gièng hÖt mét ®èi t•îng ®· cã. Hµm t¹o sao chÐp cã vÎ thùc hiÖn c¸c c«ng viÖc gièng nh• phÐp g¸n, nh•ng nÕu ®Ó ý sÏ thÊy gi÷a chóng cã chót Ýt kh¸c biÖt; phÐp g¸n thùc hiÖn viÖc sao chÐp néi dung tõ ®èi t•îng nµy sang ®èi t•îng kh¸c, do vËy c¶ hai ®èi t•îng trong phÐp g¸n ®Òu ®· tån t¹i: point p(2,3);//gi¶ thiÕt líp point cã hµm t¹o hai tham sè point q;//gi¶ thiÕt líp point cã hµm t¹o kh«ng tham sè q = p; Ng•îc l¹i, hµm t¹o thùc hiÖn ®ång thêi hai nhiÖm vô: t¹o ®èi t•îng vµ sao chÐp néi dung tõ mét ®èi t•îng ®· cã sang ®èi t•îng míi t¹o ra ®ã. Ngoµi t×nh huèng trªn ®©y, cßn cã hai tr•êng hîp cÇn dïng hµm t¹o sao chÐp: truyÒn ®èi t•îng cho hµm b»ng tham trÞ hoÆc hµm tr¶ vÒ mét ®èi t•îng nh»m t¹o mét ®èi t•îng gièng hÖt mét ®èi t•îng cïng líp ®· cã tr•íc ®ã. Trang - 58 -
  59. LËp tr×nh h•íng ®èi t•îng Hµm t¹o sao chÐp ngÇm ®Þnh Gièng nh• hµm t¹o ngÇm ®Þnh (hµm t¹o kh«ng tham sè), nÕu kh«ng ®•îc m« t¶ t•êng minh, sÏ cã mét hµm t¹o sao chÐp ngÇm ®Þnh do ch•¬ng tr×nh dÞch cung cÊp nh»m ®¶m b¶o tÝnh ®óng ®¾n cña ch•¬ng tr×nh trong c¸c t×nh huèng cÇn ®Õn hµm t¹o. Nh• vËy, trong khai b¸o cña mét líp cã Ýt nhÊt hai hµm t¹o ngÇm ®Þnh: hµm t¹o ngÇm ®Þnh vµ hµm t¹o sao chÐp ngÇm ®Þnh. Do lµ mét hµm ®•îc t¹o ra tù ®éng nªn hµm t¹o sao chÐp ngÇm ®Þnh còng chØ thùc hiÖn nh÷ng thao t¸c tèi thiÓu (“ngÇm ®Þnh”): t¹o gi¸ trÞ cña c¸c thuéc tÝnh trong ®èi t•îng míi b»ng c¸c gi¸ trÞ cña c¸c thuéc tÝnh t•¬ng øng trong ®èi t•îng cò. Nãi chung, víi c¸c líp kh«ng khai b¸o c¸c thµnh phÇn d÷ liÖu ®éng th× chØ cÇn dïng hµm t¹o sao chÐp ngÇm ®Þnh lµ ®ñ. VÊn ®Ò sÏ kh¸c ®i khi cÇn ®Õn c¸c thao t¸c qu¶n lý bé nhí ®éng trong c¸c ®èi t•îng. Trong tr•êng hîp nµy kh«ng ®•îc dïng hµm t¹o sao chÐp ngÇm ®Þnh mµ ph¶i gäi hµm t¹o sao chÐp t•êng minh. Khai b¸o vµ ®Þnh nghÜa hµm t¹o sao chÐp t•êng minh XÐt c¸c ®èi t•îng thuéc líp point. C©u lÖnh: point q=p; sÏ gäi ®Õn hµm t¹o sao chÐp. Ta còng cã thÓ viÕt theo c¸ch kh¸c nh• sau: point q(p); Tõ c¸ch viÕt trªn cã thÓ cho r»ng d¹ng cña hµm t¹o sao chÐp cho líp point cã thÓ lµ: point (point); hoÆc point(point &); Ta nhËn thÊy d¹ng thø nhÊt kh«ng dïng ®•îc v× viÖc gäi nã ®ßi hái ph¶i truyÒn cho hµm mét ®èi t•îng nh• mét tham trÞ, do ®ã g©y ra ®Ö quy v« h¹n lÇn. Víi d¹ng thø hai ta ®· thiÕt lËp mét tham chiÕu tíi ®èi t•îng nh• mét tham sè h×nh thøc truyÒn cho hµm, nªn cã thÓ chÊp nhËn ®•îc. D¹ng khai b¸o cña hµm t¹o lµ: point (point &); hoÆc point(const point &); trong ®ã tõ kho¸ const trong khai b¸o tham sè h×nh thøc chØ nh»m ng¨n cÊm mäi thay ®æi néi dung cña tham sè truyÒn cho hµm. VÝ dô 2.10: Ch•¬ng tr×nh sau ®©y bæ sung thªm hµm t¹o sao chÐp vµo líp point. #include #include Trang - 59 -
  60. LËp tr×nh h•íng ®èi t•îng class point { int x; int y; public: point(int ox = 1,int oy =0) { cout<<"Tao doi tuong : "<<this<<endl; cout<<"Dung ham thiet lap hai tham so\n"; x=ox;y=oy; } /*Hµm t¹o sao chÐp*/ point(point &p) { cout<<"Tao doi tuong : "<<this<<endl; cout<<"Dung ham thiet lap sao chep\n"; x = p.x; y = p.y; } void move(int dx, int dy) { x+=dx; y+=dy; } void display(); }; void point::display() { cout<<"Toa do : "<<x<<" "<<y<<"\n"; } point fct(point a) { point b=a; b.move(2,3); return b; } void main() Trang - 60 -
  61. LËp tr×nh h•íng ®èi t•îng { clrscr(); point a(5,2); a.display(); point b=fct(a); b.display(); getch(); } 2.4.6. Hµm huû Hµm huû lµ mét ph•¬ng thøc ®Æc biÖt cña líp cã chøc n¨ng ng•îc l¹i víi hµm t¹o. Hµm huû ®•îc gäi tr•íc khi gi¶i phãng (huû bá) mét ®èi t•îng. ViÖc huû bá mét ®èi t•îng th•êng x¶y ra trong 2 tr•êng hîp sau: Trong c¸c to¸n tö vµ c¸c hµm gi¶i phãng bé nhí nh•: delete, free Gi¶i phãng c¸c biÕn, m¶ng ®èi t•îng côc bé khi kÕt thóc hµm, ph•¬ng thøc NÕu trong líp kh«ng khai b¸o hµm huû th× mét hµm huû mÆc ®Þnh (kh«ng lµm g× c¶) sÏ ®•îc ph¸t sinh. Mét líp chØ cã mét hµm huû t•êng minh vµ ®•îc khai b¸o theo quy t¾c sau: Hµm huû kh«ng tr¶ vÒ gi¸ trÞ nªn kh«ng cÇn khai b¸o kiÓu gi¸ trÞ tr¶ vÒ cho hµm Tªn hµm huû ®•îc ®Æt gåm dÊu ~ vµ tªn líp Hµm huû kh«ng cã tham sè Chó ý: §èi víi c¸c líp ®èi t•îng cã c¸c thuéc tÝnh d¹ng con trá (thuéc tÝnh cÇn ®•îc cÊp ph¸t bé nhí tr•íc khi l•u tr÷ gi¸ trÞ) ta ph¶i khai b¸o hµm t¹o vµ hµm huû t•êng minh ®Ó c¸p ph¸t bé nhí khi ®èi t•îng míi ®•îc t¹o ra vµ thu håi bé nhí khi ®èi t•îng bÞ huû. Trang - 61 -
  62. LËp tr×nh h•íng ®èi t•îng VÝ dô 2.11: #include { #include if(top>=max) return 1; class stack else return 0; { } private: void stack::push(int x) unsigned int max; { unsigned int top; if(full()) int *a; { public: cout >max; return 0; a = new int[max]; } } top=top-1; stack::~stack() return a[top+1]; { } top = 0; void main() max = 0; { delete a; stack s;//su dung lop stack } int n; int stack::empty() cout >n; { while(n>0) if(top<=0) return 1; { else return 0; s.push(n % 2); } n = n / 2; int stack::full() } Trang - 62 -
  63. LËp tr×nh h•íng ®èi t•îng while(!s.empty()) cout int full(); #include int empty(); class stack int pop(); { void operator=(stack &x) private: { unsigned int max; top = x.top; unsigned int top; max = x.max; int *a; a = new int[max]; public: a = x.a; stack(); } ~stack(); }; void push(int x); stack::stack() Trang - 63 -
  64. LËp tr×nh h•íng ®èi t•îng { top=top+1; top=0; a[top]=x; cout >max; } a = new int[max]; int stack::pop() } { stack::~stack() if(empty()) { { top = 0; cout >n; if(top>=max) return 1; while(n>0) else return 0; { } s.push(n % 2); void stack::push(int x) n = n / 2; { } if(full()) t = s; //sö dông to¸n tö g¸n { while(!t.empty()) cout<<t.pop(); cout<<"stack day"; getch(); return; } } 2.4.8. Ph©n lo¹i c¸c ph•¬ng thøc Cã thÓ ph©n chia c¸c ph•¬ng thøc thµnh c¸c nhãm Nhãm c¸c ph•¬ng thøc th«ng th•êng: Trang - 64 -
  65. LËp tr×nh h•íng ®èi t•îng Cã ®èi ngÇm ®Þnh lµ con trá this, ®èi ngÇm ®Þnh nµy biÓu thÞ ®èi t•îng chñ thÓ trong lêi gäi ph•¬ng thøc Nhãm c¸c ph•¬ng thøc ®Ó t¹o, huû ®èi t•îng Cã ®èi ngÇm ®Þnh lµ con trá this, ®èi ngÇm ®Þnh nµy biÓu thÞ ®èi t•îng ®•îc t¹o míi (®èi víi hµm t¹o), ®èi t•îng ®•îc s¾p bÞ huû bá (®èi víi hµm huû) C¸c ph•¬ng thøc nµy kh«ng cã gi¸ trÞ tr¶ vÒ nªn kh«ng cÇn khai b¸o kiÓu tr¶ vÒ cña ph•¬ng thøc Nhãm c¸c ph•¬ng thøc to¸n tö Cã ®èi ngÇm ®Þnh lµ con trá this, ®èi ngÇm ®Þnh nµy biÓu thÞ to¸n h¹ng thø nhÊt cña to¸n tö. Tªn cña c¸c ph•¬ng thøc nµy ®•îc ®Æt gåm tõ kho¸ operator kÕt hîp víi mét to¸n tö Cã hai c¸ch gäi ph•¬ng thøc to¸n tö. Mét lµ, gäi nh• c¸c ph•¬ng thøc th«ng th•êng kh¸c. Hai lµ, sö dông nh• c¸c to¸n tö (phÐp to¸n) th«ng th•êng. Gièng nh• hµm mét ph•¬ng thøc còng cã thÓ ®•îc khai b¸o nh• ph•¬ng thøc inline (trùc tuyÕn) ®Ó gi¶m kÝch th•íc ch•¬ng tr×nh nguån vµ kh«ng lµm t¨ng thêi gian ch¹y m¸y. §Ó mét ph•¬ng thøc trë thµnh ph•¬ng thøc inline ta chØ cÇn thªm tõ kho¸ inline vµo tr•íc dßng tiªu ®Ò cña ph•¬ng thøc khi khai b¸o ph•¬ng thøc ®ã. Tuy nhiªn, ta chØ nªn sö dông ph•¬ng thøc inline ®èi víi c¸c ph•¬ng thøc ®¬n gi¶n (kh«ng chøa vßng lÆp, goto, switch, ®Ö quy ) 2.4.9. Hµm t¹o vµ ®èi t•îng thµnh phÇn Mét líp cã thuéc tÝnh lµ ®èi t•îng cña líp kh¸c ®•îc gäi lµ líp bao. VÝ dô A, B lµ hai líp, líp C cã hai thuéc tÝnh x lµ ®èi t•îng cña líp A, y lµ ®èi t•îng cña líp B. Khi ®ã, ta nãi C lµ líp bao vµ A, B lµ c¸c líp thµnh phÇn cña C. class A; class B; class C { private: A x; B y; Trang - 65 -
  66. LËp tr×nh h•íng ®èi t•îng }; V× trong c¸c ph•¬ng thøc cña líp bao kh«ng ®•îc phÐp truy nhËp vµo c¸c thµnh phÇn private cña líp thµnh phÇn nªn khi x©y dùng hµm t¹o cho líp bao, ta ph¶i sö dông hµm t¹o cña c¸c líp thµnh phÇn ®Ó khëi g¸n cho c¸c ®èi t•îng thµnh phÇn cña líp bao. Trong vÝ dô trªn khi khai b¸o hµm t¹o cho líp C, ta cÇn sö dông hµm t¹o cña líp A ®Ó khëi g¸n cho ®èi t•îng thµnh phÇn x, sö dông hµm t¹o cña líp B ®Ó khëi g¸n cho ®èi t•îng thµnh phÇn y. §Ó dïng hµm t¹o cña líp thµnh phÇn x©y dùng hµm t¹o cho líp bao, ta sö dông mÉu có ph¸p: tªn_líp(danh s¸ch ®èi): tªn_®èi_t•îng1(danh s¸ch gi¸ trÞ), tªn_®èi_t•îng2(danh s¸ch gi¸ trÞ), { //c¸c c©u lÖnh khëi g¸n gi¸ trÞ cho c¸c thuéc tÝnh kh«ng cã kiÓu ®èi t•îng } VÝ dô 2.13 : X©y dùng líp cpoint (líp ®iÓm trong mÆt ph¼ng), sau ®ã x©y dùng c¸c líp bao: cline (líp ®o¹n th¼ng) vµ ccircle (líp ®•êng trßn) nhËn líp cpoint lµm líp thµnh phÇn. #include #include #include #define pi 3.1415 class cpoint { protected: int x,y;//hoanh do va tung do public: cpoint();//ham tao khong doi cpoint(int a, int b);//ham tao co doi void move(int dx, int dy);//phep tinh tien void input();//nhap thong tin ve diem void output();//hien thi thong tin ve diem int getx();//tra ve hoanh do cua diem Trang - 66 -
  67. LËp tr×nh h•íng ®èi t•îng int gety();//tra ve tung do cua diem float kc(cpoint A) { return sqrt(pow(x-A.x,2)+pow(y-A.y,2)); } }; cpoint::cpoint() { x=0; y=0; } cpoint::cpoint(int a, int b) { x=a; y=b; } void cpoint::move(int dx, int dy) { x+=dx; y+=dy; } void cpoint::input() { cout >x; cout >y; } void cpoint::output() { cout<<"("<<x<<","<<y<<")"; } int cpoint::getx() { return x; Trang - 67 -
  68. LËp tr×nh h•íng ®èi t•îng } int cpoint::gety() { return y; } class cline:cpoint { private: cpoint startpoint;//diem dau cpoint endpoint;//diem cuoi public: cline():startpoint(),endpoint() { } cline(int x1, int y1, int x2, int y2):startpoint(x1,y1),endpoint(x2,y2) { } float length();//tinh do dai doan thang void input();//nhap thong tin void output();//hien thi thong tin }; void cline::input() { cout<<"Diem dau:\n"; cpoint::input(); endpoint.input(); } void cline::output() { cout<<"\nDiem dau:"; cpoint::output(); cout<<"\nDiem cuoi:"; endpoint.output(); Trang - 68 -
  69. LËp tr×nh h•íng ®èi t•îng cout<<"\nChieu dai doan thang:"<<length(); } float cline::length() { int x1,y1,x2,y2; x1=startpoint.getx(); y1=startpoint.gety(); x2=endpoint.getx(); y2=endpoint.gety(); return sqrt(pow(x1-x2,2)+pow(y1-y2,2)); } class ccircle { private: cpoint center;//toa do tam int radius;//ban kinh public: ccircle():center() { radius = 0; } ccircle(int x, int y, int r):center(x,y) { radius = r; } void input();//nhap void output();//hien thi float area();//tinh dien tich }; void ccircle::input() { cout<<"Toa do tam:\n"; center.input(); Trang - 69 -
  70. LËp tr×nh h•íng ®èi t•îng cout >radius; } void ccircle::output() { cout<<"\nToa do tam:"; center.output(); cout<<"\nBan kinh:"<<radius; cout.width(10); cout.precision(2); cout<<"\nDien tich hinh tron:"<<area(); } float ccircle::area() { return pi*radius*radius; } void main() { cline d; d.output(); ccircle c; c.output(); getch(); } 2.5. C¸c thµnh phÇn tÜnh 2.5.1. Thµnh phÇn d÷ liÖu tÜnh Th«ng th•êng, trong cïng mét ch•¬ng tr×nh c¸c ®èi t•îng thuéc cïng mét líp chØ së h÷u c¸c thµnh phÇn d÷ liÖu cña riªng nã. VÝ dô, nÕu chóng ta ®Þnh nghÜa líp exple1 b»ng: class exple1 { int n; Trang - 70 -
  71. LËp tr×nh h•íng ®èi t•îng float x; } sau ®ã khai b¸o: exple1 a,b; sÏ t¹o ra hai ®èi t•îng a,b së h÷u riªng biÖt hai vïng d÷ liÖu kh¸c nhau nh• h×nh vÏ: a.n b.n a.x b.x object a object b Cã thÓ cho phÐp nhiÒu ®èi t•îng cïng chia sÎ d÷ liÖu b»ng c¸ch ®Æt tõ kho¸ static tr•íc khai b¸o thµnh phÇn d÷ liÖu t•¬ng øng. VÝ dô, nÕu ta ®Þnh nghÜa líp exple2 b»ng: class exple2 { static int n; float x; }; th× khai b¸o: exple2 a,b; t¹o ra hai ®èi t•îng cã chung thµnh phÇn n: a.n b.n a.x b.x Nh• vËy, viÖc chØ ®Þnh static ®èi víi mét thµnh phÇn d÷ liÖu cã ý nghÜa lµ trong toµn bé líp, chØ cã mét thÓ hiÖn duy nhÊt cña thµnh phÇn ®ã. Thµnh phÇn static ®•îc dïng chung cho tÊt c¶ c¸c ®èi t•îng cña líp ®ã vµ nã vÉn chiÕm gi÷ vïng nhí ngay c¶ khi kh«ng khai b¸o bÊt kú ®èi t•îng nµo. Cã thÓ nãi r»ng, c¸c thµnh phÇn d÷ liÖu tÜnh gièng nh• c¸c biÕn toµn côc trong ph¹m vi líp. Trang - 71 -
  72. LËp tr×nh h•íng ®èi t•îng Kh«ng thÓ khëi g¸n gi¸ trÞ cho thµnh phÇn static b»ng c¸c hµm t¹o cña mét líp. Còng kh«ng thÓ khëi t¹o lóc khai b¸o c¸c thµnh phÇn d÷ liÖu static nh• trong vÝ dô sau: class exple2 { static int n=2; //lçi }; Mét thµnh phÇn d÷ liÖu static ph¶i ®•îc khëi t¹o mét c¸ch t•êng minh bªn ngoµi khai b¸o líp b»ng mét chØ thÞ nh• sau: int exple2::n = 5; Trong C++ viÖc khëi t¹o gi¸ trÞ nh• thÕ nµy kh«ng vi ph¹m tÝnh riªng t• cña c¸c ®èi t•îng. Chó ý r»ng cÇn ph¶i cã tªn líp vµ to¸n tö ph¹m vi ®Ó chØ ®Þnh c¸c thµnh phÇn cña líp ®•îc khëi t¹o. Ngoµi ra, kh¸c víi c¸c biÕn toµn côc th«ng th•êng, c¸c thµnh phÇn d÷ liÖu static kh«ng ®•îc khëi t¹o ngÇm ®Þnh lµ 0. Ch•¬ng tr×nh counter.cpp sau ®©y minh ho¹ c¸ch sö dông vµ thao t¸c víi thµnh phÇn d÷ liÖu static, dïng ®Ó ®Õm sè ®èi t•îng hiÖn ®ang ®•îc sö dông: VÝ dô 2.14: #include #include class counter { static int count; //®Õm sè ®èi t•îng ®•îc t¹o ra public : counter (); ~ counter (); }; int counter::count = 0;//khëi t¹o gi¸ trÞ cho thµnh phÇn static //hµm t¹o counter:: counter () { cout<<"++Tao : bay gio co "<<++count<<" doi tuong\n"; Trang - 72 -
  73. LËp tr×nh h•íng ®èi t•îng } counter:: ~counter () { cout :: ( ) TÊt nhiªn vÉn cã thÓ gäi c¸c ph•¬ng thøc tÜnh th«ng qua c¸c ®èi t•îng. Tuy nhiªn c¸ch gäi th«ng qua tªn líp trùc quan h¬n v× ph¶n ¸nh ®•îc b¶n chÊt cña ph•¬ng thøc tÜnh. Th«ng th•êng, c¸c ph•¬ng thøc tÜnh ®•îc dïng ®Ó xö lý chung trªn tÊt c¶ c¸c ®èi t•îng cña líp, ch¼ng h¹n ®Ó hiÖn thÞ c¸c th«ng tin liªn quan ®Õn c¸c thµnh phÇn d÷ liÖu static. Trang - 73 -
  74. LËp tr×nh h•íng ®èi t•îng VÝ dô 2.15: Ch•¬ng tr×nh c¶i tiÕn tõ vÝ dô 2.14 b»ng c¸ch thªm mét ph•¬ng thøc tÜnh trong líp counter. #include #include class counter { static int count; public : counter (); ~ counter (); static void counter_display(); }; int counter::count = 0; void counter::counter_display() { cout<<"Hien dang co "<<count<<" doi tuong \n"; } counter:: counter () { cout<<"++Tao : bay gio co "<<++count<<" doi tuong\n"; } counter:: ~counter () { cout<<" Xoa : bay gio con "<< count<<" doi tuong\n"; } void main() { clrscr(); void fct(); counter a; fct(); counter::counter_display(); Trang - 74 -
  75. LËp tr×nh h•íng ®èi t•îng counter b; } void fct() { counter u; counter::counter_display();//gäi qua tªn líp counter v; v.counter_display();//gäi qua ®èi t•îng } 2.6. Khëi g¸n m¶ng ®èi t•îng Sau khi khai b¸o líp, ta cã thÓ dïng tªn líp ®Ó khai b¸o m¶ng ®èi t•îng gièng nh• c¸ch khai b¸o m¶ng cã kiÓu d÷ liÖu chuÈn kh¸c theo mÉu có ph¸p: Tªn_líp Tªn_m¶ng[kÝch cì]; VÝ dô: cpoint P[100]; C©u lÖnh khai b¸o m¶ng sÏ gäi tíi hµm t¹o kh«ng ®èi ®Ó t¹o c¸c phÇn tö m¶ng. Trong vÝ dô trªn, hµm t¹o kh«ng ®èi cña líp cpoint ®•îc gäi 100 lÇn ®Ó t¹o 100 phÇn tö m¶ng ®èi t•îng. §Ó khai b¸o m¶ng vµ khëi g¸n gi¸ trÞ cho c¸c phÇn tö m¶ng ®èi t•îng, ta sö dông hµm t¹o cã ®èi theo mÉu có ph¸p: Tªn_líp Tªn_m¶ng[kÝch cì] = {tªn_líp(c¸c tham sè), tªn_líp(c¸c tham sè), }; VÝ dô: cpoint P[5] = {cpoint(0,0), cpoint(10,0), cpoint(10,10)}; C©u lÖnh khai b¸o trªn sÏ yªu cÇu gäi hµm t¹o cã ®èi 3 lÇn vµ gäi hµm t¹o kh«ng ®èi 2 lÇn ®Ó sinh ra 5 ®èi t•îng cña líp cpoint. §Ó truy nhËp vµo c¸c thµnh phÇn cña phÇn tö m¶ng ®èi t•îng, ta sö dông có ph¸p : Tªn_m¶ng[chØ sè phÇn tö].Tªn_thuéc_tÝnh //truy nhËp vµo thuéc tÝnh //truy nhËp vµo ph•¬ng thøc Tªn_m¶ng[chØ sè phÇn tö].Tªn_ph•¬ng_thøc(danh s¸ch ®èi); Trang - 75 -
  76. LËp tr×nh h•íng ®èi t•îng 2.7. CÊp ph¸t bé nhí cho ®èi t•îng Cã thÓ dïng to¸n tö new ®Ó cÊp ph¸t bé nhí cho mét hoÆc mét d·y c¸c ®èi t•îng. Bé nhí ®•îc cÊp ph¸t ®•îc qu¶n lý bëi con trá kiÓu ®èi t•îng. VÝ dô, ta cã thÓ cÊp ph¸t bé nhí cho c¸c ®èi t•îng cña líp cpoint nh• sau : cpoint *p, *q ; p = new cpoint ; q = new cpoint[10] ; §Ó truy nhËp vµo c¸c thµnh phÇn cña ®èi t•îng th«ng qua con trá ®èi t•îng, ta sö dông có ph¸p : Tªn_con_trá->tªn_thuéc_tÝnh //truy nhËp vµo thuéc tÝnh Tªn_con_trá->tªn_ph•¬ng_thøc //gäi ph•¬ng thøc VÝ dô : p->x ; p->y ; p->input() ; §Ó biÓu thÞ ®èi t•îng th«ng qua con trá ®èi t•îng, ta viÕt *Tªn_con_trá VÝ dô : *p NÕu q lµ con trá ®èi t•îng trá tíi ®Þa chØ ®Çu vïng nhí cña mét d·y ®èi t•îng. Khi ®ã, ®Ó truy nhËp vµo c¸c thµnh phÇn cña ®èi t•îng thø i trong d·y, ta viÕt : q[i].tªn_thµnh_phÇn hoÆc (q+i)->tªn_thµnh_phÇn 2.8. §èi t•îng h»ng, ph•¬ng thøc h»ng a) §èi t•îng h»ng Còng nh• c¸c phÇn tö d÷ liÖu kh¸c, mét ®èi t•îng cã thÓ ®•îc khai b¸o lµ h»ng. C¸c ph•¬ng thøc duy cã thÓ sö dông cho c¸c ®èi t•îng h»ng lµ c¸c hµm t¹o vµ hµm huû. Bëi lÏ c¸c ®èi t•îng h»ng kh«ng thÓ thay ®æi, mµ chØ ®•îc t¹o ra hoÆc huû bá ®i. Tuy nhiªn, khi xö lý c¸c ®èi t•îng h»ng b»ng c¸c ph•¬ng thøc kh¸c th× ch•¬ng tr×nh dÞch sÏ c¶nh b¸o (warning): Non-const function called for const object nh•ng ch•¬ng tr×nh EXE vÉn ®•îc t¹o ra vµ khi thùc hiÖn ch•¬ng tr×nh, th× néi dung c¸c ®èi t•îng h»ng vÉn bÞ thay ®æi. VÝ dô 2.16: #include #include int uscln(int a, int b) Trang - 76 -
  77. LËp tr×nh h•íng ®èi t•îng { while(a!=b) if(a>b) a=a-b; else b=b-a; return a; } class phanso { private: int ts; int ms; public: phanso() { ts=0; ms=1; } phanso(int a, int b) { ts=a; ms=b; } ~phanso() { ts=0; ms=1; } void nhap() { cout >ts; cout >ms; } void hienthi(); Trang - 77 -
  78. LËp tr×nh h•íng ®èi t•îng void rutgon(); }; void phanso::rutgon() { int usc; usc=uscln(ts,ms); ts=ts/usc; ms=ms/usc; } void phanso::hienthi() { cout<<ts<<"/"<<ms; } void main() { const phanso ps = phanso(3,6);//khai b¸o ®èi t•îng h»ng cout<<"\nPhan so ban dau:"; ps.hienthi();//gäi ph•¬ng thøc xö lý ®èi t•îng h»ng cout<<"\nPhan so sau khi rut gon:"; ps.rutgon();//gäi ph•¬ng thøc xö lý ®èi t•îng h»ng ps.hienthi(); getch(); } Khi dÞch ch•¬ng tr×nh, ch•¬ng tr×nh dÞch sÏ ®•a ra c¸c c¶nh b¸o sau: Non-const function phanso::hienthi called for const object Non-const function phanso::rutgon called for const object Vµ khi ch¹y ch•¬ng tr×nh ta thu ®•îc kÕt qu¶: Phan so ban dau:3/6 Phan so sau khi rut gon:1/2 b) Ph•¬ng thøc h»ng Ph•¬ng thøc cña líp ®•îc khai b¸o víi tõ kho¸ const ®øng ngay sau danh s¸ch c¸c tham sè h×nh thøc ®•îc gäi lµ ph•¬ng thøc h»ng. Trang - 78 -
  79. LËp tr×nh h•íng ®èi t•îng Ph•¬ng thøc h»ng kh«ng thÓ thay ®æi néi dung mét ®èi t•îng. Mét ph•¬ng thøc h»ng ph¶i ®•îc m« t¶ c¶ trong khai b¸o vµ khi ®Þnh nghÜa. Ph•¬ng thøc h»ng cã thÓ ®•îc ®Þnh nghÜa chång b»ng mét ph•¬ng thøc kh«ng ph¶i ph•¬ng thøc h»ng. VÝ dô 2.17: #include #include int uscln(int a, int b) { while(a!=b) if(a>b) a=a-b; else b=b-a; return a; } class phanso { private: int ts; int ms; public: phanso() { ts=0; ms=1; } phanso(int a, int b) { ts=a; ms=b; } ~phanso() { ts=0; Trang - 79 -
  80. LËp tr×nh h•íng ®èi t•îng ms=1; } void nhap() { cout >ts; cout >ms; } void hienthi() ; void rutgon() const; }; void phanso::rutgon() const; { int usc; usc=uscln(ts,ms); ts=ts/usc; ms=ms/usc; } void phanso::hienthi() { cout<<ts<<"/"<<ms; } void main() { const phanso ps = phanso(3,6);//khai b¸o ®èi t•îng h»ng cout<<"\nPhan so ban dau:"; ps.hienthi();//gäi ph•¬ng thøc xö lý ®èi t•îng h»ng cout<<"\nPhan so sau khi rut gon:"; ps.rutgon();//gäi ph•¬ng thøc h»ng xö lý ®èi t•îng h»ng ps.hienthi(); getch(); } Khi ch¹y ch•¬ng tr×nh, ch•¬ng tr×nh dÞch sÏ b¸o lçi: Trang - 80 -
  81. LËp tr×nh h•íng ®èi t•îng Cannot modify const object t¹i dßng lÖnh ts=ts/usc; trong th©n cña ph•¬ng thøc rutgon. V× vËy, viÖc dïng ph•¬ng thøc h»ng cho c¸c ®èi t•îng h»ng sÏ ®¶m b¶o gi÷ nguyªn néi dung cña c¸c ®èi t•îng h»ng. 2.9. Hµm b¹n, líp b¹n C¸c thµnh phÇn private cña ®èi t•îng chØ cã thÓ truy nhËp bëi c¸c ph•¬ng thøc cña chÝnh líp ®ã. Ngoµi ra, ph•¬ng thøc cña líp cßn cã thÓ truy nhËp ®Õn tÊt c¶ thµnh phÇn private cña c¸c ®èi t•îng cïng líp ®•îc khai b¸o côc bé bªn trong ph•¬ng thøc ®ã hoÆc ®•îc truyÒn nh• lµ tham sè cña ph•¬ng thøc (cã thÓ b»ng tham trÞ , b»ng tham chiÕu hay b»ng con trá). Muèn mét hµm kh«ng ph¶i thµnh phÇn cña líp cã thÓ truy nhËp vµo c¸c thµnh phÇn cña líp ta sö dông “hµm b¹n”. Khi ®Þnh nghÜa mét líp, cã thÓ khai b¸o r»ng mét hay nhiÒu hµm b¹n; khai b¸o b¹n bÌ nh• thÕ cho phÐp c¸c hµm nµy truy xuÊt ®•îc tíi c¸c thµnh phÇn private cña líp gièng nh• c¸c ph•¬ng thøc cña líp ®ã. ¦u ®iÓm cña ph•¬ng ph¸p nµy lµ kiÓm so¸t c¸c truy nhËp ë cÊp ®é líp. Khi tÊt c¶ c¸c ph•¬ng thøc cña mét líp lµ hµm b¹n cña mét líp kh¸c, ta cã kh¸i niÖm líp b¹n. VÝ dô ®Ó thiÕt lËp tÊt c¶ c¸c ph•¬ng thøc cña líp B lµ b¹n cña líp A th× trong khai b¸o líp A, ta ®•a ra chØ thÞ: friend class B; Trang - 81 -
  82. LËp tr×nh h•íng ®èi t•îng C©u hái vµ bµi tËp 1. Trong c¸c khai b¸o líp sau, nh÷ng khai b¸o nµo lµ ®óng: a. class MyClass; b. Class MyClass; c. class MyClass{ }; d. Class MyClass{ }; 2. Gi¶ sö ta ®· ®Þnh nghÜa líp MyClass, b©y giê ta khai b¸o mét ®èi t•îng thuéc kiÓu líp nµy. Khai b¸o nµo lµ ®óng: a. class MyClass me; b. MyClass me; c. MyClass me(); d. MyClass me{}; 3. Trong c¸c khai b¸o thuéc tÝnh ngay trong ph¹m vi cña khai b¸o líp MyClass nh• sau, nh÷ng khai b¸o nµo lµ ®óng: a. int myAge; b. private int myAge; c. public int myAge; d. private: int myAge; 4. Trong c¸c khai b¸o ph•¬ng thøc ngay trong ph¹m vi cña khai b¸o líp MyClass nh• sau, nh÷ng khai b¸o nµo lµ ®óng: a. public: void show(); b. void show(); c. void show(){cout << “hello!”;}; d. void MyClass::show(){cout << “hello!”;} 5. XÐt ®o¹n ch•¬ng tr×nh sau: class MyClass { int age; public: int getAge(); }; MyClass me; Khi ®ã, trong c¸c lÖnh sau, lÖnh nµo cã thÓ thªm vµo cuèi ®o¹n ch•¬ng tr×nh trªn: Trang - 82 -
  83. LËp tr×nh h•íng ®èi t•îng a. cout > me.age; 6. Trong c¸c khai b¸o hµm khëi t¹o cho líp MyClass nh• sau, nh÷ng khai b¸o nµo lµ ®óng: a. myClass(); b. MyClass(); c. MyClass(MyClass); d. void MyClas(); e. MyClass MyClass(); 7. Trong c¸c khai b¸o hµm hñy cho líp MyClass nh• sau, nh÷ng khai b¸o nµo lµ ®óng: a. ~myClass(); b. ~MyClass(); c. ~MyClass(MyClass); d. void ~MyClas(); e. MyClass ~MyClass(); 8. Gi¶ sö ta khai b¸o líp MyClass cã mét thuéc tÝnh age vµ mét hµm khëi t¹o: class MyClass { int age; public: MyClass(MyClass me){ }; int getAge(){return age}; }; Trong c¸c dßng lÖnh sau, nh÷ng dßng nµo cã thÓ xuÊt hiÖn trong hµm khëi t¹o trªn: a. age = MyClass.age; b. age = me.age; c. age = MyClass.getAge(); Trang - 83 -
  84. LËp tr×nh h•íng ®èi t•îng d. age = me.getAge(); e. age = 10; 9. XÐt khai b¸o líp nh• sau: class MyClass { public: MyClass(MyClass); MyClass(int); }; Trong sè c¸c khai b¸o ®èi t•îng sau, nh÷ng khai b¸o nµo lµ ®óng: a. MyClass me; b. MyClass me(); c. MyClass me(10); d. MyClass me1(10), me2(me1); 10. XÐt khai b¸o líp nh• sau: class MyClass{ public: MyClass();}; Trong sè c¸c khai b¸o con trá ®èi t•îng sau, nh÷ng khai b¸o nµo lµ ®óng: a. MyClass *me; b. MyClass *me(); c. MyClass *me = new me(); d. MyClass *me = new MyClass(); 11. XÐt khai b¸o líp nh• sau: class MyClass { public: MyClass(int i=0, int j=0, float k=0); }; Trong sè c¸c khai b¸o con trá ®èi t•îng sau, nh÷ng khai b¸o nµo lµ ®óng: a. MyClass *me; b. MyClass *me = new MyClass(); c. MyClass *me = new MyClass(1, 20); Trang - 84 -
  85. LËp tr×nh h•íng ®èi t•îng d. MyClass *me = new MyClass(1, 20, 30); 12. Khai b¸o mét líp nh©n viªn, cã tªn lµ Employee, víi ba thuéc tÝnh cã tÝnh chÊt private: - Tªn nh©n viªn, cã d¹ng mét con trá kiÓu char - Tuæi nh©n viªn, cã kiÓu int - Lu¬ng nh©n viªn, cã kiÓu float. 13. Thªm vµo líp Employee trong bµi 12 c¸c ph•¬ng thøc cã tÝnh chÊt public: - set/get gi¸ trÞ thuéc tÝnh tªn nh©n viªn - set/get gi¸ trÞ thuéc tÝnh tuæi nh©n viªn - set/get gi¸ trÞ thuéc tÝnh lu¬ng nh©n viªn. 14. ViÕt mét hµm khëi t¹o kh«ng cã tham sè cho líp Employee trong bµi 13, c¸c thuéc tÝnh cña líp nhËn gi¸ trÞ mÆc ®Þnh: - gi¸ trÞ thuéc tÝnh tªn nh©n viªn, mÆc ®Þnh lµ chuçi kÝ tù rçng “” - gi¸ trÞ thuéc tÝnh tuæi nh©n viªn, mÆc ®Þnh lµ 18 - gi¸ trÞ thuéc tÝnh lu¬ng nh©n viªn, mÆc ®Þnh lµ $100. 15. ViÕt thªm mét hµm khëi t¹o víi ®Çy ®ñ ba tham sè t•¬ng øng víi ba thuéc tÝnh cña líp Employee trong bµi 14. 16. Thªm vµo líp Employee mét ph•¬ng thøc show() ®Ó giíi thiÖu vÒ tªn, tuæi vµ l•¬ng cña ®èi t•îng nh©n viªn. 17. ViÕt mét hµm hñy t•êng minh cho líp Employee nh»m gi¶i phãng vïng nhí cña con trá char, lµ kiÓu cña thuéc tÝnh tªn nh©n viªn. 18. ViÕt mét ch•¬ng tr×nh sö dông líp Employee ®•îc x©y dùng sau bµi 17 víi c¸c thao t¸c sau: - Khai b¸o mét ®èi t•îng kiÓu Employee, dïng hµm khëi t¹o kh«ng tham sè - Dïng hµm show() ®Ó giíi thiÖu vÒ ®èi t•îng ®ã 19. ViÕt mét ch•¬ng tr×nh sö dông líp Employee ®•îc x©y dùng sau bµi 17 víi c¸c thao t¸c sau: - Khai b¸o mét ®èi t•îng kiÓu Employee, dïng hµm khëi t¹o kh«ng tham sè - NhËp tõ bµn phÝm gi¸ trÞ c¸c thuéc tÝnh tªn, tuæi, l•¬ng nh©n viªn. - G¸n c¸c gi¸ trÞ nµy cho c¸c thuéc tÝnh cña ®èi t•îng ®· khai b¸o, dïng c¸c hµm set - Dïng hµm show() ®Ó giíi thiÖu vÒ ®èi t•îng ®ã Trang - 85 -
  86. LËp tr×nh h•íng ®èi t•îng 20. ViÕt mét ch•¬ng tr×nh sö dông líp Employee ®•îc x©y dùng sau bµi 17 víi c¸c thao t¸c sau: - Khai b¸o mét ®èi t•îng kiÓu Employee, dïng hµm khëi t¹o vëi ®ñ 3 tham sè - Dïng hµm show() ®Ó giíi thiÖu vÒ ®èi t•îng ®ã 21. ViÕt mét ch•¬ng tr×nh sö dông líp Employee ®•îc x©y dùng sau bµi 17 víi c¸c thao t¸c sau: - Khai b¸o mét con trá ®èi t•îng kiÓu Employee - CÊp ph¸t bé nhí, dïng hµm khëi t¹o vëi ®ñ 3 tham sè - Dïng hµm show() ®Ó giíi thiÖu vÒ ®èi t•îng mµ con trá nµy ®ang trá tíi 22. ViÕt mét ch•¬ng tr×nh nhËp d÷ liÖu cho mét m¶ng ®éng c¸c ®èi t•îng cña líp Employee trong bµi 17. ChiÒu dµi m¶ng ®éng còng ®•îc nhËp tõ bµn phÝm. 23. ViÕt mét ch•¬ng tr×nh t×m kiÕm trªn m¶ng ®éng ®· ®•îc x©y dùng trong bµi 22: t×m kiÕm vµ giíi thiÖu vÒ nh©n viªn trÎ nhÊt vµ nh©n viªn giµ nhÊt trong m¶ng ®ã. 24. ViÕt mét ch•¬ng tr×nh t×m kiÕm trªn m¶ng ®éng ®· ®•îc x©y dùng trong bµi 22: t×m kiÕm vµ giíi thiÖu vÒ nh©n viªn cã l•¬ng cao nhÊt vµ nh©n viªn cã l•¬ng thÊp nhÊt trong m¶ng ®ã. 25. ViÕt mét ch•¬ng tr×nh t×m kiÕm trªn m¶ng ®éng ®· ®•îc x©y dùng trong bµi 22: t×m kiÕm vµ giíi thiÖu vÒ nh©n viªn cã tªn x¸c ®Þnh, do ng•êi dïng nhËp tõ bµn phÝm. 26. ViÕt mét ch•¬ng tr×nh khai b¸o líp ph©n sè, x©y dùng c¸c ph•¬ng thøc vµ ph•¬ng thøc to¸n tö ®Ó: a. NhËp mét ph©n sè tõ bµn phÝm b. HiÓn thÞ mét ph©n sè ra mµn h×nh c. Rót gän mét ph©n sè ®Õn d¹ng ph©n sè tèi gi¶n d. TÝnh tæng hai ph©n sè e. TÝnh hiÖu hai ph©n sè f. TÝnh tÝch hai ph©n sè g. TÝnh th•¬ng hai ph©n sè 27. ViÕt mét ch•¬ng tr×nh khai b¸o líp sè phøc, x©y dùng c¸c ph•¬ng thøc vµ ph•¬ng thøc to¸n tö ®Ó: a. NhËp mét sè phøc tõ bµn phÝm b. HiÓn thÞ mét sè phøc ra mµn h×nh Trang - 86 -
  87. LËp tr×nh h•íng ®èi t•îng c. TÝnh tæng hai sè phøc d. TÝnh hiÖu hai sè phøc e. TÝnh tÝch hai sè phøc f. TÝnh th•¬ng hai sè phøc 28. ViÕt mét ch•¬ng tr×nh khai b¸o líp ®a thøc bËc n, x©y dùng c¸c ph•¬ng thøc vµ ph•¬ng thøc to¸n tö ®Ó: a. NhËp mét ®a thøc tõ bµn phÝm b. HiÓn thÞ mét ®a thøc ra mµn h×nh c. TÝnh tæng hai ®a thøc d. TÝnh hiÖu hai ®a thøc e. TÝnh tÝch hai ®a thøc 29. ViÕt mét ch•¬ng tr×nh khai b¸o líp Stack, x©y dùng hµm t¹o vµ c¸c ph•¬ng thøc ®Ó: a. Khëi t¹o Stack rçng b. KiÓm tra Stack ®Çy c. KiÓm tra Stack rçng d. Bæ sung mét phÇn tö vµo Stack e. Lo¹i bá phÇn tö ë ®Ønh Stack Sö dông Stack ®Ó kiÓm tra mét x©u ký tù cã ph¶i x©u ®èi xøng kh«ng? 30. ViÕt mét ch•¬ng tr×nh khai b¸o líp ma trËn vu«ng cÊp n, x©y dùng c¸c ph•¬ng thøc vµ ph•¬ng thøc to¸n tö ®Ó: a. NhËp mét ma trËn tõ bµn phÝm b. HiÓn thÞ mét ma trËn ra mµn h×nh c. TÝnh tæng hai ma trËn d. TÝnh hiÖu hai ma trËn e. TÝnh tÝch hai ma trËn f. T×m ma trËn chuyÓn vÞ Trang - 87 -