Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 35 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
35
Dung lượng
1,06 MB
Nội dung
NGƠN NGỮ LẬP TRÌNH Bài 9: Đa hình Hàm ảo Giảng viên: Lý Anh Tuấn Email: tuanla@tlu.edu.vn Nội dung Cơ hàm ảo ◦ ◦ ◦ ◦ Kết gán muộn Thi hành hàm ảo Khi sử dụng hàm ảo Lớp trừu tượng hàm ảo túy Con trỏ hàm ảo ◦ Sự tương thích kiểu mở rộng ◦ Ép lên ép xuống ◦ Chi tiết hàm ảo Cơ hàm ảo Đa hình ◦ Liên kết nhiều ngữ nghĩa với hàm ◦ Hàm ảo cung cấp khả ◦ Là nguyên tắc lập trình hướng đối tượng Ảo ◦ Tồn chất thực tế không tồn Hàm ảo ◦ Có thể sử dụng trước định nghĩa Ví dụ hình vẽ Lớp số kiểu hình vẽ ◦ Hình chữ nhật (rectangle), hình trịn (circle), hình ovan (oval), vân vân ◦ Mỗi hình vẽ đối tượng lớp khác Dữ liệu hình chữ nhật: độ cao, chiều rộng, tâm điểm Dữ liệu hình trịn: tâm điểm, bán kính Tất dẫn xuất từ lớp cha: Figure Hàm cần thiết: draw() ◦ Các thị khác cho hình vẽ Ví dụ hình vẽ: center() Mỗi lớp cần hàm draw khác Có thể gọi draw lớp: Rectangle r; Circle c; r.draw(); //Gọi hàm draw lớp Rectangle c.draw(); // Gọi hàm draw lớp Circle Lớp cha Figure bao gồm hàm áp dụng cho tất hình vẽ; chẳng hạn: center(): di chuyển hình vẽ vào tâm hình ◦ Xóa hình ban đầu, sau vẽ lại ◦ Do Figure::center() gọi hàm draw để vẽ lại ◦ Vấn đề: Gọi hàm draw() từ lớp nào? Ví dụ hình vẽ: Hình Xét kiểu hình vẽ sau: lớp Triangle dẫn xuất từ lớp Figure Hàm center() kế thừa từ Figure ◦ Nó có làm việc với triangle khơng? ◦ Nó sử dụng draw() khác với hình khác ◦ Nó sử dụng Figure::draw() khơng làm việc với triangle Cần hàm center() kế thừa sử dụng hàm Triangle::draw() hàm Figure::draw() ◦ Nhưng lớp Triangle chí cịn chưa viết viết Figure::center() Ví dụ hình vẽ: Hình ảo Câu trả lời sử dụng hàm ảo Nói cho biên dịch: ◦ Không biết hàm thi hành ◦ Đợi sử dụng chương trình ◦ Sau nhận thi thành từ thể đối tượng Được gọi kết gán muộn kết gán động ◦ Hàm ảo thi hành kết gán muộn Một ví dụ khác Chương trình lưu trữ hồ sơ cửa hàng phụ tùng ô tô ◦ ◦ ◦ ◦ Theo dõi giao dịch Chưa biết biết tất giao dịch Ban đầu có giao dịch bán lẻ Sau đó: Giao dịch giảm giá, thư đặt hàng, vân vân Phụ thuộc vào nhân tố khác bên cạnh giá thuế Hàm ảo: Phụ tùng tơ Chương trình phải: ◦ Tính tốn doanh thu tổng cộng hàng ngày ◦ Tính tốn giao dịch lớn nhất/nhỏ ngày ◦ Có thể tính giá trị trung bình giao dịch ngày Tất đến từ hóa đơn riêng lẻ ◦ Nhưng nhiều hàm tính tốn hóa đơn thêm vào sau Khi kiểu giao dịch khác thêm vào Do hàm tính tốn hóa đơn ảo Định nghĩa lớp Sale class Sale { public: Sale(); Sale(double thePrice); double getPrice() const; virtual double bill() const; double savings(const Sale& other) const; private: double price; }; 10 Lớp sở trừa tượng Hàm ảo túy khơng địi hỏi phải định nghĩa ◦ Bắt tất lớp dẫn xuất định nghĩa phiên riêng chúng Lớp với nhiều hàm ảo túy là: lớp sở trùy tượng ◦ Có thể sử dụng lớp sở ◦ Khơng có đối tượng tạo từ Vì khơng có định nghĩa hồn chỉnh cho tất thành viên Nếu lớp dẫn xuất thất bại việc định nghĩa tất hàm ảo túy ◦ Nó lớp sở trừu tượng 21 Tương thích kiểu mở rộng Biết rằng: Derived lớp dẫn xuất Base ◦ Các đối tượng Derived gán cho đối tượng kiểu Base ◦ Nhưng ngược lại khơng Xét ví dụ trước: ◦ Một DiscountSale Sale ngược lại khơng 22 Ví dụ tương thích kiểu mở rộng class Pet { public: string name; virtual void print() const; }; class Dog : public Pet { public: string breed; virtual void print() const; }; 23 Lớp Pet Dog Bây cung cấp khai báo: Dog vdog; Pet vpet; Lưu ý biến thành viên name breed public ◦ Chỉ nhằm mục đích ví dụ, khơng điển hình 24 Sử dụng lớp Pet Dog Một chó thú cưng: ◦ vdog.name = "Tiny"; vdog.breed = "Great Dane"; vpet = vdog; ◦ Những lệnh phép Có thể gán giá trị cho kiểu cha, ngược lại khơng ◦ Một thú cưng khơng phải chó 25 Vấn đề tách lớp Lưu ý giá trị gán cho vpet trường breed ◦ coutbreed = "Great Dane"; ppet = pdog; Không thể truy cập trường breed đối tượng trỏ tới ppet: cout breed; //Khong hop le 28 Ví dụ vấn đề tách lớp Phải sử dụng hàm thành viên ảo: ppet->print(); ◦ Gọi hàm thành viên print lớp Dog Bởi ảo C++ đợi để xem đối tượng trỏ ppet trỏ tới trước gọi kết gán 29 Hàm hủy ảo Nhắc lại: hàm hủy cần để hủy cấp phát liệu cấp phát động Xét: Base *pBase = new Derived; … delete pBase; ◦ Sẽ gọi hàm hủy lớp sở trỏ tới đối tượng lớp Derived ◦ Khai báo hàm hủy virtual để chỉnh sửa vấn đề Có thể để tất hàm hủy ảo 30 Ép kiểu Xét: Pet vpet; Dog vdog; … vdog = static_cast(vpet); //Không hợp lệ! Không thể ép thú cưng thành chó, nhưng: vpet = vdog; // Legal! vpet = static_cast(vdog); //Also legal! Ép kiểu lên thực ◦ Từ kiểu hậu duệ đến kiểu tổ tiên 31 Ép kiểu xuống Ép kiểu xuống nguy hiểm ◦ Ép từ kiểu tổ tiên xuống kiểu hậu duệ ◦ 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 sử dụng do: ◦ Phải theo dõi tất thông tin thêm vào ◦ Tất hàm thành viên phải ảo 32 Công việc nội hàm ảo Khơng cần biết sử dụng ◦ Quy tắc che dấu thông tin Bảng hàm ảo ◦ Bộ biên dịch tạo ◦ Có trỏ cho hàm thành viên ảo ◦ Trỏ tới vị trí mã lệnh hàm Các đối tượng lớp có trỏ ◦ Các trỏ trỏ tới bảng hàm ảo 33 Tóm tắt Kết gán muộn hỗn việc định hàm thành viên gọi chương trình chạy ◦ Trong C++ hàm ảo sử dụng kết gán muộn Các hàm ảo túy khơng có định nghĩa ◦ Các lớp có hàm ảo túy trừu tượng ◦ Không có đối tượng tạo từ lớp trừu tượng ◦ Được sử dụng làm sở cho lớp khác dẫn xuất 34 Tóm tắt Đối tượng lớp dẫn xuất gán cho đối tượng lớp sở ◦ Các thành viên lớp sở bị mất: vấn đề tách lớp Phép gán trỏ đối tượng động ◦ Cho phép chỉnh sửa vấn đề tách lớp Khai báo tất hàm hủy ảo ◦ Áp dụng tốt cho việc lập trình ◦ Đảm bảo nhớ hủy cấp phát 35