Bài giảng Lập trình hướng đối tượng - Thừa kế Cài đặt trong C++

Ví dụ MotorVehicle

Định nghĩa các lớp con

Quyền truy nhập - Access privilege

Từ khoá protected

 

 

ppt27 trang | Chuyên mục: Lập Trình Hướng Đối Tượng | Chia sẻ: dkS00TYs | Lượt xem: 1881 | Lượt tải: 2download
Tóm tắt nội dung Bài giảng Lập trình hướng đối tượng - Thừa kế Cài đặt trong C++, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
Thừa kế:Cài đặt trong C++ Lập trình hướng đối tượng Tài liệu đọc Eckel, Bruce. Thinking in C++, 2nd Ed. Vol 1. Chapter 14: Inheritance & Composition Skip p. 612 (Operator Overloading & Inheritance) to p. 614 (Incremental Development) Dietel. C++ How to Program, 4th Ed. Chapter 7: Object-Oriented Programming: Inheritance Tổng quan	 Ví dụ MotorVehicle Định nghĩa các lớp con Quyền truy nhập - Access privilege Từ khoá protected Ví dụ MotorVehicle Nhớ lại ví dụ về cây thừa kế Ví dụ MotorVehicle Bắt đầu bằng định nghĩa lớp cơ sở, MotorVehicle class MotorVehicle { public: MotorVehicle(int vin, string make, string model); ~MotorVehicle(); void drive(int speed, int distance); private: int vin; string make; string model; }; Ví dụ MotorVehicle Tiếp theo, định nghĩa constructor, destructor,và hàm drive() (ở đây, ta chỉ định nghĩa tạm drive()) MotorVehicle::MotorVehicle(int vin, string make, string model) { this->vin = vin; this->make = make; this->model = model; } MotorVehicle::~MotorVehicle() {} // We could actually use // the default destructor void MotorVehicle::drive(int speed, int distance) { cout MyBaseClass {...}; class Car : public MotorVehicle { public: Car (int passengers); ~Car(); private: int passengers; }; Chỉ rõ quan hệ giữa lớp con Car và lớp cha MotorVehicle Định nghĩa lớp con Hiện giờ constructor của lớp Car chỉ nhận 1 tham số passengers, trong khi các đối tượng Car cũng có tất cả các thành viên được thừa kế từ MotorVehicle 	 	Car (int passengers); Do vậy, trừ khi ta muốn dùng giá trị mặc định cho các thành viên được thừa kế, ta nên truyền thêm tham số cho constructor để khởi tạo vin, make, model. Định nghĩa lớp con Bổ sung các tham số cho constructor, ta có khai báo: class Car : public MotorVehicle { public: Car (int vin, string make, string model, int passengers); ~Car(); private: int passengers; }; Quy ước: đặt các tham số cho lớp cha lên đầu danh sách. Định nghĩa lớp con Tiếp theo, định nghĩa lớp mới Tối thiểu, ta sẽ định nghĩa constructor và (có thể cả) destructor Các lớp con không thừa kế constructor và destructor của lớp cha, do việc khởi tạo và huỷ các lớp khác nhau là khác nhau Phiên bản constructor đầu tiên mà ta có thể nghĩ tới: Car::Car(int vin, string make, string model, int passengers) { this->vin = vin; this->make = make; this->model = model; this->passengers = passengers; } Car::~Car() {} Định nghĩa lớp con Nhược điểm trực tiếp truy nhập các thành viên dữ liệu của lớp cơ sở thiếu tính đóng gói : phải biết sâu về chi tiết lớp cơ sở và phải can thiệp sâu không tái sử dụng mã khởi tạo của lớp cơ sở không thể khởi tạo các thành viên private của lớp cơ sở do không có quyền truy nhập Nguyên tắc: một đối tượng thuộc lớp con bao gồm một đối tượng lớp cha cộng thêm các tính năng bổ sung của lớp con một thể hiện của lớp cơ sở sẽ được tạo trước, sau đó "gắn" thêm các tính năng bổ sung của lớp dẫn xuất Vậy, ta sẽ sử dụng constructor của lớp cơ sở. Định nghĩa lớp con Để sử dụng constructor của lớp cơ sở, ta dùng danh sách khởi tạo của constructor (tương tự như khi khởi tạo các hằng thành viên) cách duy nhất để tạo phần thuộc về thể hiện của lớp cha tạo trước nhất Ta sửa định nghĩa constructor như sau: Car::Car(int vin, string make, string model, int passengers) : MotorVehicle(vin, make, model) { this->passengers = passengers; } Định nghĩa lớp con Để đảm bảo rằng một thể hiện của lớp cơ sở luôn được tạo trước, nếu ta bỏ qua lời gọi constructor lớp cơ sở tại danh sách khởi tạo của lớp dẫn xuất, trình biên dịch sẽ tự động chèn thêm lời gọi constructor mặc định của lớp cơ sở Tuy ta cần gọi constructor của lớp cơ sở một cách tường minh, tại destructor của lớp dẫn xuất, lời gọi tượng tự cho destructor của lớp cơ sở là không cần thiết việc này được thực hiện tự động Định nghĩa lớp con Khi tạo thể hiện của một lớp dẫn xuất, các constructor được gọi bắt đầu từ lớp cơ sở nhất và chuyển dần về phía lớp dẫn xuất Khi huỷ thể hiện của lớp dẫn xuất, các destructor được gọi bắt đầu từ lớp dẫn xuất, lên dần qua các lớp cơ sở (thứ tự ngược lại) Định nghĩa lớp con Tương tự, khai báo và định nghĩa của lớp Truck như sau: class Truck : public MotorVehicle { public: Truck (int vin, string make, string model, int maxPayload); ~Truck(); void Load(); void Unload(); private: int maxPayload; }; Truck::Truck(int vin, string make, string model, int maxPayload) : MotorVehicle(vin, make, model) { this->maxPayload = maxPayload; } Truck::~Truck() {} void Truck::Load() {…} void Truck::Unload() {…} Quyền truy nhập(Access privilege) Ta đã sử dụng hai kiểu quyền truy nhập cho các thành viên dữ liệu và phương thức public - thành viên/phương thức có thể được truy nhập từ mọi đối tượng C++ thuộc phạm vi private - thành viên/phương thức chỉ có thể được truy nhập từ bên trong chính lớp đó Còn có kiểu quyền truy nhập thứ ba: protected class Car : public MotorVehicle { public: Car (...); ~Car(); private: int passengers; }; Quyền truy nhập Quay lại cây thừa kế với MotorVehicle là lớp cơ sở Mọi thành viên dữ liệu đều được khai báo private, do đó chúng chỉ có thể được truy nhập từ các thể hiện của MotorVehicle tất cả các lớp dẫn xuất không có quyền truy nhập các thành viên private của MotorVehicle Vậy, đoạn mã sau sẽ có lỗi class MotorVehicle { ... private: int vin; string make; string model; }; void Truck::Load() { if (this->make == “Ford”) { ... } } Quyền truy nhập Tuy quy định quyền truy nhập như trên có vẻ kỳ cục, nhưng nó đảm bảo tính đóng gói nếu không, ta có thể lấy được quyền truy nhập vào cấu trúc bên trong của một lớp chỉ bằng cách tạo một lớp dẫn xuất của lớp đó Trường hợp nếu ta xây dựng lớp cơ sở và cố ý muốn “cấp” cho lớp dẫn xuất quyền truy nhập tới một số thành viên/phương thức, từ khoá protected quy định quyền truy nhập cho các thành viên/phương thức sẽ được sử dụng bởi lớp dẫn xuất Quyền truy nhập Từ khoá protected dùng để cấp quyền truy nhập tới thành viên/phương thức của một lớp cho các lớp dẫn xuất (và chỉ các lớp dẫn xuất) của lớp đó Đối với mọi đối tượng khác của C++, các thành viên/phương thức protected được coi như private (chúng đều không thể truy nhập được) Tuy tiêu chí đóng gói khuyên nên để mọi thứ private, nhưng khi tạo các cây thừa kế, người ta thường hay cấp quyền truy nhập protected Quyền truy nhập Giả sử ta muốn các lớp con của MotorVehicle có thể truy nhập dữ liệu của nó Thay từ khoá private bằng protected, ta có khai báo: class MotorVehicle { ... protected: int vin; string make; string model; }; void Truck::Load() { if (this->make == “Ford”) { ... } } Vậy, đoạn mã sau sẽ không có lỗi Tuy nhiên truy nhập từ bên ngoàivẫn sẽ bị cấm Quyền truy nhập Các quyền truy nhập có vai trò gì trong quan hệ thừa kế? Bây giờ, ta chuyển sang cách sử dụng các từ khoá quyền truy nhập trong khai báo lớp để chỉ kiểu thừa kế class Car : public MotorVehicle { ... }; Quyền truy nhập Các quyền truy nhập có vai trò gì trong quan hệ thừa kế? Bây giờ, ta chuyển sang cách sử dụng các từ khoá quyền truy nhập trong khai báo lớp để chỉ kiểu thừa kế class Car : private MotorVehicle { ... }; class Car : protected MotorVehicle { ... }; class Car : public MotorVehicle { ... }; Kiểu thừa kế Từ khoá được dùng để chỉ rõ “kiểu” thừa kế được sử dụng nó quy định những ai có thể "nhìn thấy" quan hệ thừa kế đó Nhắc lại: lớp Car thừa kế lớp MotorVehicle có nghĩa các đối tượng Car cũng có các thành viên dữ liệu và phương thức của MotorVehicle. “nhìn thấy” quan hệ thừa kế giữa Car và MotorVehicle nghĩa là có thể truy nhập tới các thành viên mà Car được thừa kế từ MotorVehicle. Kiểu thừa kế Thừa kế public (loại thông dụng nhất): quan hệ thừa kế được nhìn thấy từ mọi nơi mọi đối tượng C++ khi tương tác với một thể hiện của lớp con đều có thể coi nó như một thể hiện của lớp cha có thể truy nhập mọi thành viên/phương thức public của lớp cha nói cách khác, các thành viên được thừa kế giữ nguyên quyền truy nhập các thành viên public của cha cũng được coi như public của con các thành viên protected của cha cũng được coi như protected của con class Car : public MotorVehicle { ... }; Kiểu thừa kế Thừa kế private: chỉ có chính thể hiện đó biết nó được thừa kế từ lớp cha các đối tượng bên ngoài không thể truy nhập các thành viên được thừa kế Nói cách khác, mọi thành viên được thừa kế đều trở thành private trong lớp con Có thể dùng thừa kế private để tạo lớp con có mọi chức năng/dịch vụ của lớp cha nhưng lại không cho bên ngoài biết về các chức năng đó. class Car : private MotorVehicle { ... }; Kiểu thừa kế Khi dùng kiểu thừa kế protected, ngoài lớp được thừa kế, chỉ có các lớp con của lớp đó nhìn thấy quan hệ thừa kế quan hệ “Car thừa kế MotorVehicle” sẽ được nhìn thấy từ bên trong Car các lớp con của Car nói cách khác, các thành viên được thừa kế sẽ có quyền truy nhập bị hạ xuống protected. class Car : protected MotorVehicle { ... }; 

File đính kèm:

  • pptBài giảng Lập trình hướng đối tượng - Thừa kế Cài đặt trong C++.ppt