1. Trang chủ
  2. » Công Nghệ Thông Tin

Bài giảng Ngôn ngữ lập trình Bài 8 Lê Nguyễn Tuấn Thành

32 189 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 32
Dung lượng 458,97 KB

Nội dung

Bài giảng Ngôn ngữ lập trình Bài 8 Đa hình và hàm ảo cung cấp cho người học các kiến thức Đa hình (Polymorphism), cơ bản về Hàm ảo (Virtual Function), con trỏ và Hàm ảo. Mời các bạn cùng tham khảo. Bài giảng Ngôn ngữ lập trình Bài 8 Đa hình và hàm ảo cung cấp cho người học các kiến thức Đa hình (Polymorphism), cơ bản về Hàm ảo (Virtual Function), con trỏ và Hàm ảo. Mời các bạn cùng tham khảo.

NGÔN NGỮ LẬP TRÌNH Bài 8: Đa Hình Hàm Ảo Giảng viên: Lê Nguyễn Tuấn Thành Email: thanhlnt@tlu.edu.vn Bộ Môn Công Nghệ Phần Mềm – Khoa CNTT Trường Đại Học Thủy Lợi NỘI DUNG Đa hình (Polymorphism) Cơ Hàm ảo (Virtual Function)  Gắn kết trễ (Late binding)  Cài đặt hàm ảo  Khi sử dụng hàm ảo?  Hàm ảo (Pure Virtual Function) Lớp trừu tượng (Abstract Class) Con trỏ Hàm ảo    Mở rộng tương thích kiểu Ép kiểu lên (Upcasting) Ép kiểu xuống (Downcasting) Bài giảng có sử dụng hình vẽ sách “Practical Debugging in C++, A Ford and T Teorey, Prentice Hall, 2002” ĐA HÌNH (POLYMORPHISM) Một ba trụ cột quan trọng OOP  Đa hình (Polymorphism) tượng đối tượng thuộc lớp khác hiểu thông điệp theo cách khác  Ví dụ: thông điệp “nhảy”, kangaroo cóc nhảy hai kiểu khác   Chúng có hành vi “nhảy” nội dung hành vi khác CƠ BẢN  VỀ HÀM ẢO Hàm ảo   Hàm ảo cung cấp khả đa hình Hàm “sử dụng” trước thực định nghĩa VÍ DỤ VỚI CÁC LỚP MÔ TẢ HÌNH VẼ (1/5) HÀM THÀNH VIÊN DRAW()  Xây dựng lớp cho nhiều kiểu hình vẽ khác   Hình chữ nhật, hình tròn, hình oval … Mỗi hình cụ thể đối tượng lớp Dữ liệu hình chữ nhật: chiều cao, chiều rộng  Dữ liệu hình tròn: tâm, bán kính  Tất lớp kế thừa từ lớp cha: Figure  Các lớp có hàm draw()    Mục đích vẽ hình hình Mỗi lớp có cài đặt khác tương ứng với loại hình vẽ VÍ DỤ VỚI CÁC LỚP MÔ TẢ HÌNH VẼ (2/5) SỬ DỤNG HÀM THÀNH VIÊN DRAW() Mỗi lớp cần định nghĩa hàm draw() riêng  Có thể gọi hàm draw() lớp, ví dụ: Rectangle r; Circle c; r.draw(); // Gọi hàm draw lớp Rectangle c.draw(); // Gọi hàm draw lớp Circle   Điều bình thường, chưa có đặc biệt đây! VÍ DỤ VỚI CÁC LỚP MÔ TẢ HÌNH VẼ (3/5): HÀM THÀNH VIÊN CENTER() Lớp cha Figure bao gồm hàm áp dụng cho “tất cả” hình vẽ  Xét hàm center() để di chuyển hình vẽ từ vị trí tới vị trí trung tâm hình     Cách làm: xóa hình vị vị trí tại, sau vẽ lại vị trí trung tâm hình Hàm Figure::center() sử dụng (gọi) hàm draw() để vẽ lại hình Câu hỏi: Hàm draw() gọi?  Từ lớp nào?  VÍ DỤ VỚI CÁC LỚP MÔ TẢ HÌNH VẼ (4/5): ĐỊNH NGHĨA LỚP HÌNH VẼ MỚI   Xét lớp hình vẽ mới: lớp Triangle kế thừa từ lớp Figure Hàm center() lớp Triangle kế thừa từ lớp cha Figure Liệu hàm có hoạt động với lớp Triangle?  Hàm sử dụng hàm draw() riêng lớp Triangle!  Nếu hàm sử dụng hàm Figure::draw() -> không hoạt động với lớp Triangle   Muốn: kế thừa hàm center() để sử dụng hàm Triangle::draw() KHÔNG PHẢI hàm Figure::draw() Nhưng lớp Triangle CHƯA ĐƯỢC định nghĩa hàm Figure::center() định nghĩa!  Không biết tồn lớp Triangle  VÍ DỤ VỚI CÁC LỚP MÔ TẢ HÌNH VẼ (5/5): HÀM ẢO Hàm ảo câu trả lời cho vấn đề  Nói với trình biên dịch:      Không biết hàm cài đặt Đợi sử dụng chương trình Sau lấy phần cài đặt từ đối tượng cụ thể Được gọi gắn kết trễ (late binding) gắn kết động (dynamic binding)  Những hàm ảo cài đặt chế late binding VÍ DỤ DOANH SỐ BÁN HÀNG  (1/2) Xây dựng chương trình giúp lưu trữ hồ sơ cho cửa hàng phụ tùng ô tô     Mục đích: lưu trữ doanh số bán hàng Không lường trước hết tất loại doanh số bán hàng Đầu tiên doanh số bán lẻ thông thường Sau đó: doanh số bán hàng giảm giá, doanh số bán hàng qua thư điện tử, …  Phụ thuộc vào nhiều yếu tố giá, thuế … 10 THỰC THI  Để giải thích liên quan đến khái niệm gắn kết trễ (late binding)     HÀM ẢO BẰNG CÁCH NÀO? Hàm ảo cài đặt late binding Nói trình biên dịch đợi hàm sử dụng chương trình Quyết định phiên hàm sử dụng dựa đối tượng gọi Một khái niệm quan trọng OOP 18 GHI ĐÈ (OVERRIDING)  Định nghĩa hàm ảo thay đổi lớp kế thừa  Chúng ta gọi “ghi đè” (overidden)  Khác với nạp chồng (overloading) ? Tương tự định nghĩa lại cho hàm chuẩn  Phân biệt:    Hàm ảo thay đổi: ghi đè (overidden) Hàm bình thường thay đổi: định nghĩa lại (redefined) 19 ĐIỂM YẾU CỦA VIỆC SỬ DỤNG HÀM ẢO Bỏ qua tất lợi ích hàm ảo thấy  Hàm ảo có bất lợi lớn: phụ phí (overhead)!     Sử dụng nhiều nhớ Gắn kết trễ (late binding) khiến chương trình chạy chậm Vì hàm ảo không thật cần thiết không nên sử dụng 20 HÀM ẢO THUẦN (PURE VIRTUAL FUNCTIONS)  Lớp sở định nghĩa có nghĩa cho vài thành viên nó!   Nhớ lại lớp Figure    Mục đích đơn giản lớp khác kế thừa Tất hình vẽ đối tượng lớp kế thừa cụ thể Ví dụ: Rectangle, Circle, Triangle, … Lớp Figure ý niệm việc cách vẽ được! Tạo hàm ảo thuần: virtual void draw() = 0; 21 LỚP CƠ SỞ TRỪU TƯỢNG (ABSTRACT BASE CLASSES)  Các hàm ảo không yêu cầu định nghĩa   Lớp với hay nhiều hàm ảo gọi là: lớp sở trừu tượng    Bắt buộc lớp kế thừa phải định nghĩa phiên hàm riêng Chỉ sử dụng lớp sở Không thể tạo đối tượng từ lớp trừu tượng Bởi định nghĩa hoàn thiện tất thành viên! Nếu lớp thừa kế không định nghĩa tất hàm ảo => Nó lớp sở trừu tượng 22 MỞ RỘNG TƯƠNG THÍCH KIỂU (TYPE COMPATIBILITY)  Giả sử D lớp kế thừa từ lớp sở B    Đối tượng lớp D gán cho đối tượng lớp sở B Nhưng ngược lại không thể! Xét ví dụ trước:  Một đối tượng DiscountSale “là” Sale, điều ngược lại không 23 TƯƠNG THÍCH KIỂU – VÍ DỤ  class Pet { public: string name; virtual void print() const; }; class Dog : public Pet { public: string breed; virtual void print() const; }; 24 SỬ DỤNG HAI LỚP PET VÀ DOG Xét khai báo sau: Dog vdog; Pet vpet;  Chú ý biến thành viên name breed public! Chỉ nhằm mục đích minh họa  Tất thứ “là” dog “là” pet  vdog.name = "Tiny"; vdog.breed = "Great Dane"; vpet = vdog;  Có thể gán giá trị kiểu lớp cha, chiều ngược lại  Một pet “không là” dog 25 VẤN ĐỀ MẤT MÁT THÔNG TIN (SLICING)  Chú ý giá trị gán vpet, biến thành viên breed bị    cout name = "Tiny"; pdog->breed = "Great Dane"; ppet = pdog;  Không thể truy cập trường breed đối tượng trỏ tới pet: cout breed; // Không hợp lệ!  Phải sử dụng hàm ảo thành viên: ppet->print();   Gọi hàm thành viên print() lớp Dog!   Bởi hàm ảo C++ đợi để nhìn đối tượng trỏ mà ppet thực trỏ tới trước lời gọi gắn kết (binding) 27 HÀM HỦY ẢO (VIRTUAL DESTRUCTORS) Hàm hủy cần giải phóng động liệu cấp phát  Xét ví dụ:  Base *pBase = new Derived; … delete pBase;     Sẽ gọi hàm hủy lớp sở pBase trỏ tới đối tượng lớp Derived! Xây dựng hàm hủy ảo giải vấn đề này! Cách tốt định nghĩa tất hàm hủy hàm ảo 28 ÉP KIỂU (CASTING) Xét ví dụ: Pet vpet; Dog vdog; … vdog = static_cast(vpet); // Không hợp lệ!  Không thể ép pet thành dog, nhưng: vpet = vdog; // Hợp lệ! vpet = static_cast(vdog); // Hợp lệ!  Ép kiểu lên (upcasting) hợp lệ   Từ kiểu cháu lên kiểu tổ tiên 29 ÉP KIỂU XUỐNG (DOWNCASTING)  Ép kiểu xuống nguy hiểm!    Ép từ kiểu tổ tiên thành kiểu cháu Giả sử thông tin thêm vào Có thể thực với dynamic_cast Pet *ppet; ppet = new Dog; Dog *pdog = dynamic_cast(ppet);   Hợp lệ, nguy hiểm Ép kiểu xuống dùng số nhược điểm   Phải kiểm tra xem tất thông tin có thêm vào hay không Tất hàm thành viên phải hàm ảo 30 TÓM TẮT  Gắn kết trễ (late binding) trì hoãn định việc hàm thành viên gọi chạy chương trình   Trong C++, hàm ảo sử dụng chế gắn kết trễ Hàm ảo định nghĩa Một lớp với hàm ảo gọi lớp trừu tượng  Không thể tạo đối tượng từ lớp trừu tượng  Được sử dụng chặt chẽ sở lớp kế thừa khác   Đối tượng lớp kế thừa gán cho đối tượng lớp sở Có thể vài thông tin lớp kế thừa bị => vấn đề cắt lát  Gán trỏ đối tượng động cho phép giải vấn đề mát thông tin (slicing)   Nên định nghĩa tất hàm hủy hàm ảo  Đảm bảo nhớ giải phóng cách 31 GIÁO TRÌNH THAM KHẢO Giáo trình chính: W Savitch, Absolute C++, Addison Wesley, 2002  Tham khảo:    A Ford and T Teorey, Practical Debugging in C++, Prentice Hall, 2002 Nguyễn Thanh Thủy, Kĩ thuật lập trình C++, NXB Khoa học Kĩ Thuật, 2006 32 ... cập trường breed đối tượng trỏ tới pet: cout breed; // Không hợp lệ!  Phải sử dụng hàm ảo thành viên: ppet->print();   Gọi hàm thành viên print() lớp Dog!   Bởi hàm ảo C++ đợi để... NÀO? Hàm ảo cài đặt late binding Nói trình biên dịch đợi hàm sử dụng chương trình Quyết định phiên hàm sử dụng dựa đối tượng gọi Một khái niệm quan trọng OOP 18 GHI ĐÈ (OVERRIDING)  Định nghĩa... chiếu đến biến thành viên breed kể đối xử Pet Có thể làm với trỏ trỏ đến biến động 26 GIẢI QUYẾT VẤN ĐỀ SLICING Pet *ppet; Dog *pdog; pdog = new Dog; pdog->name = "Tiny"; pdog->breed = "Great

Ngày đăng: 15/05/2017, 10:13

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w