Kế thừa cơ bản
Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 48 trên 104.
Kế thừa (inheritance) cho phép một lớp có các thuộc tính và hành vi của một lớp khác. Lớp được kế thừa gọi là lớp cơ sở (hoặc lớp cha), còn lớp kế thừa gọi là lớp dẫn xuất (hoặc lớp con).
Để tạo lớp dẫn xuất, hãy dùng dấu hai chấm, theo sau là phạm vi truy cập và tên lớp cơ sở:
class Animal {
public:
std::string name;
void eat() {
std::cout << name << " is eating" << std::endl;
}
};
class Dog : public Animal {
public:
void bark() {
std::cout << name << " says woof!" << std::endl;
}
};Lớp Dog giờ có thể truy cập cả name và eat() từ Animal, đồng thời có phương thức bark() riêng. Đây chính là bản chất của kế thừa (inheritance): tái sử dụng code có sẵn trong khi bổ sung chức năng mới.
Dog myDog;
myDog.name = "Buddy";
myDog.eat(); // Kế thừa từ Animal
myDog.bark(); // Định nghĩa trong DogTừ khóa public đứng trước Animal xác định kiểu kế thừa. Kế thừa công khai có nghĩa là các thành viên công khai của lớp cơ sở vẫn công khai trong lớp dẫn xuất. Đây là hình thức phổ biến nhất và mô hình hóa mối quan hệ “là một”: Dog là một Animal.
Thử thách
DễHãy xây dựng một hệ thống phân cấp phương tiện đơn giản để minh họa cách tính kế thừa hoạt động. Bạn sẽ tạo lớp cơ sở Vehicle và lớp dẫn xuất Motorcycle mở rộng lớp đó với hành vi chuyên biệt.
Bạn sẽ sắp xếp code trong ba tệp:
Vehicle.h: Định nghĩa lớp cơ sởVehiclevới:- Một thành viên công khai
std::string brand - Một thành viên công khai
int year - Một phương thức công khai
displayInfo()in ra hãng và năm sản xuất của phương tiện theo định dạng:Brand: <brand>, Year: <year>
- Một thành viên công khai
Motorcycle.h: Định nghĩa lớpMotorcyclekế thừa công khai từVehicle. Lớp dẫn xuất này cần bổ sung:- Một thành viên công khai
int engineCCbiểu thị dung tích động cơ - Một phương thức công khai
revEngine()in ra:<brand> goes vroom vroom!
Lớp
Motorcyclesẽ tự động kế thừabrand,yearvàdisplayInfo()từVehicle.- Một thành viên công khai
main.cpp: Đọc ba đầu vào, mỗi đầu vào trên một dòng riêng:- Tên hãng (chuỗi)
- Năm sản xuất (số nguyên)
- Dung tích động cơ tính bằng CC (số nguyên)
Tạo một đối tượng
Motorcycle, gán giá trị cho các thành viên được kế thừa (brandvàyear) cũng như thành viên riêngengineCC. Sau đó tạo ba dòng đầu ra theo thứ tự: trước tiên gọi phương thức được kế thừadisplayInfo(), tiếp theo tự in dung tích động cơ bằngstd::cout << "Engine: " << moto.engineCC << "cc" << std::endl;, cuối cùng gọi phương thức riêng của xe máyrevEngine(). Cách này minh họa tính kế thừa bằng việc sử dụng cả phương thức được kế thừa lẫn phương thức riêng của lớp dẫn xuất.Định dạng đầu ra:
Brand: <brand>, Year: <year> Engine: <engineCC>cc <brand> goes vroom vroom!
Ví dụ, với các đầu vào Harley, 2022 và 1200:
Brand: Harley, Year: 2022
Engine: 1200cc
Harley goes vroom vroom!Đừng quên thêm header guard vào các tệp header và dùng #include "Vehicle.h" trong header của Motorcycle để truy cập lớp cơ sở.
Tự làm thử
#include <iostream>
#include <string>
#include "Motorcycle.h"
using namespace std;
int main() {
string brand;
int year;
int engineCC;
cin >> brand;
cin >> year;
cin >> engineCC;
// TODO: Tạo một đối tượng Motorcycle
// TODO: Gán giá trị cho các thành viên brand, year và engineCC
// TODO: Gọi displayInfo() để hiển thị thông tin kế thừa
// TODO: In ra thông tin động cơ theo định dạng: Engine: <engineCC>cc
// TODO: Gọi revEngine() để minh họa hành vi riêng của xe máy
return 0;
}
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Lập trình hướng đối tượng
1Nền tảng về OOP
Tệp bên ngoàiBiên dịch và tạo bản dựng C++Tệp header và tệp nguồnNamespace và phạm viGiới thiệu về OOP trong C++Lớp và đối tượngCon trỏ thisPhương thức (hàm thành viên)Thuộc tính (dữ liệu thành viên)Cơ bản về hàm khởi tạo và hàm hủyÔn tập: máy tính đơn giản4Thuộc tính của lớp
Thành viên đối tượng và thành viên tĩnhHàm truy xuất và hàm thiết lậpHàm thành viên hằngTừ khóa mutablePhương thức và biến tĩnhHàm và lớp bạnÔn tập: Trình quản lý tài khoản ngân hàng7Kế thừa
Kế thừa cơ bảnMức truy cập trong kế thừaThứ tự gọi hàm khởi tạo và hàm hủyGhi đè phương thứcHàm ảo và VTableĐa kế thừaKế thừa ảoÔn tập: hệ phân cấp nhân viên2Quản lý bộ nhớ
Bộ nhớ ngăn xếp và heapCon trỏ và tham chiếuBộ nhớ động (new/delete)Con trỏ thông minh trong C++RAII trong C++Ôn tập: Trình quản lý mảng động5Tính đóng gói
Phạm vi truy cập trong C++Tìm hiểu sâu về phạm vi truy cậpẨn thông tinStruct và lớpLớp lồng nhau và lớp bên trongÔn tập: hệ thống hồ sơ sinh viên8Đa hình
Đa hình lúc biên dịch và khi chạyNạp chồng hàmÔn lại hàm ảoHàm ảo thuần túyLớp trừu tượngThiết kế interface trong C++Ép kiểu động và RTTIÔn tập: Máy tính hình học3Hàm khởi tạo và hàm hủy
Hàm khởi tạo mặc địnhHàm khởi tạo có tham sốHàm khởi tạo sao chépHàm khởi tạo di chuyểnDanh sách khởi tạoHàm khởi tạo ủy quyềnTìm hiểu sâu về hàm hủyQuy tắc 3 / 5 / 0Ôn tập: lớp chuỗi6Nạp chồng toán tử
Giới thiệu về nạp chồng toán tửNạp chồng toán tử số họcNạp chồng toán tử so sánhToán tử luồngNạp chồng toán tử gánNạp chồng toán tử [] và ()Toán tử chuyển đổi kiểuÔn tập: lớp ma trận9Mẫu
Mẫu hàmMẫu lớpChuyên biệt hóa mẫuMẫu biến tham sốCơ bản về SFINAE và đặc điểm kiểuÔn tập: vùng chứa tổng quátTự luyện tập: Trình biên dịch C++ online