Đang tải...

[C++ OOP Thực Chiến] Bài 35: Đặc tính cơ bản của kế thừa đơn - Sự truyền ngôi của các Class!

10/05/2026
4 phút đọc
[C++ OOP Thực Chiến] Bài 35: Đặc tính cơ bản của kế thừa đơn - Sự truyền ngôi của các Class!
Chào anh em! Hãy tưởng tượng bạn đang viết phần mềm quản lý nhân sự cho một công ty IT. Ban đầu, bạn tạo một Class `NhanVien` với các thuộc tính cơ bản: `ho...

Chào anh em! Hãy tưởng tượng bạn đang viết phần mềm quản lý nhân sự cho một công ty IT. Ban đầu, bạn tạo một Class NhanVien với các thuộc tính cơ bản: hoTen, tuoi, luongCoBan và hàm chamCong().

Sau đó, công ty tuyển thêm vị trí Kỹ sư Backend. Bạn cần một Class DevBackend. Anh Dev này cũng là nhân viên, nên anh ta cũng có họ tên, tuổi, lương cơ bản và cũng phải chấm công. Nhưng anh ta lại có thêm kỹ năng đặc thù là ngonNguCode (Golang, PHP) và hàm deployServer().

Chẳng lẽ bạn lại mở một file mới, gõ lại y chang mớ code của NhanVien rồi mới nhét thêm ngonNguCode vào? Quá cồng kềnh! C++ cho phép Class DevBackend xin "kế thừa" lại toàn bộ tài sản của Class NhanVien.

1. Kế thừa (Inheritance) là gì?

Kế thừa là cơ chế cho phép một Class mới (Lớp con) được tạo ra dựa trên một Class đã tồn tại (Lớp cha).

  • Lớp cha (Base Class / Super Class): Nơi chứa những đặc điểm chung nhất. (Ví dụ: NhanVien)
  • Lớp con (Derived Class / Sub Class): Nhận lại toàn bộ tài sản của Lớp cha, đồng thời có thể "độ" thêm những vũ khí, thuộc tính của riêng nó. (Ví dụ: DevBackend)

Mối quan hệ "IS-A" (Là một): Kế thừa chỉ hợp lý khi bạn có thể nói: "Lớp Con LÀ MỘT Lớp Cha".

  • DevBackend LÀ MỘT NhanVien -> Hợp lý! Cho kế thừa.
  • NhanVien LÀ MỘT DevBackend -> Sai! (Có người là HR, Tester).

2. Cú pháp truyền ngôi (Kế thừa đơn)

"Kế thừa đơn" nghĩa là một Lớp con chỉ có duy nhất một Lớp cha (1 cha 1 con). Cú pháp trong C++ sử dụng dấu hai chấm : như sau:

class LopCon : public LopCha {
 // Các thuộc tính và phương thức mới bổ sung thêm
};

Từ khóa public ở đây là một Access Modifier (Bổ ngữ truy cập) dùng cho kế thừa. Nó quyết định xem tài sản của cha khi truyền xuống cho con sẽ bị biến đổi quyền hạn như thế nào. Hiện tại, chúng ta luôn dùng public để giữ nguyên bản chất của tài sản.

3. Code Demo: Quản lý nhân sự công ty công nghệ

Hãy cùng xem mã nguồn của chúng ta được "rút gọn" thần kỳ như thế nào khi có Kế thừa:

#include <iostream>
#include <string>

using namespace std;

// --- LỚP CHA (BASE CLASS) ---
class NhanVien {
public: // Tạm thời dùng public để lớp con dễ dàng truy cập
 string hoTen;
 double luongCoBan;

 NhanVien(string ten, double luong) {
 hoTen = ten;
 luongCoBan = luong;
 }

 void chamCong() {
 cout << "[System] Nhan vien " << hoTen << " da diem danh luc 8:00 AM.n";
 }
};

// --- LỚP CON (DERIVED CLASS) ---
// DevBackend kế thừa toàn bộ tài sản của NhanVien
class DevBackend : public NhanVien {
public:
 string ngonNguCode; // Thuộc tính bổ sung của riêng Dev

 // Constructor của lớp con phải gọi Constructor của lớp cha
 DevBackend(string ten, double luong, string ngonNgu) 
 : NhanVien(ten, luong) // Truyền dữ liệu ngược lên cho Cha xây dựng
 {
 ngonNguCode = ngonNgu;
 }

 // Phương thức bổ sung của riêng Dev
 void deployServer() {
 cout << "[Action] " << hoTen << " dang deploy he thong bang " << ngonNguCode << "...n";
 }
};

int main() {
 cout << "--- HE THONG QUAN LY NHAN SU ---nn";

 // 1. Tạo một nhân viên bình thường
 NhanVien hr("Nguyen Van A", 1000.0);
 hr.chamCong();
 // hr.deployServer(); // LỖI NGAY! Nhân viên thường không biết deploy!

 cout << "n-------------------nn";

 // 2. Tạo một Dev Backend
 DevBackend dev("Tran Van B", 2500.0, "Golang & PHP");
 
 // ĐIỀU KỲ DIỆU CỦA KẾ THỪA:
 // Mặc dù trong class DevBackend không hề có hàm chamCong() và biến hoTen,
 // nhưng object 'dev' vẫn có thể xài được vì đã thừa kế từ Lớp cha!
 dev.chamCong(); 
 
 // Gọi kỹ năng riêng của Lớp con
 dev.deployServer();

 return 0;
}

Nhận xét: Anh em có thấy hàm chamCong() không hề được viết lại trong class DevBackend nhưng vẫn gọi được mượt mà không? Đây chính là sức mạnh của tái sử dụng mã nguồn. Nếu sau này hệ thống thay đổi giờ chấm công từ 8:00 thành 8:30, bạn chỉ cần sửa ở ĐÚNG MỘT NƠI (Lớp cha), toàn bộ các Lớp con sẽ tự động cập nhật theo!

Tạm kết & Gợi mở

Chúng ta vừa dạo bước qua khái niệm cơ bản nhất của kế thừa. Cơ chế này giúp thiết kế hệ thống trở nên phân tầng, rõ ràng và cực kỳ dễ bảo trì.

Nhưng khoan đã, hãy nhìn lại class NhanVien (Lớp cha) trong đoạn code trên. Mình đã cố tình đặt hoTenluongCoBan ở chế độ public để Lớp con DevBackend dễ lấy ra xài trong hàm deployServer(). Nhưng ở các bài trước, chúng ta đã thề non hẹn biển rằng: "Dữ liệu luôn luôn phải nằm trong private để đảm bảo Đóng gói (Encapsulation)!"

Vậy nếu chúng ta đưa hoTen về lại private, liệu thằng Lớp con có còn nhìn thấy và xài được tài sản của cha nó nữa không? Quy luật của C++ khắc nghiệt đến mức nào?

Sự xung đột nảy lửa giữa Đóng gói và Kế thừa sẽ được giải quyết trong bài tiếp theo. Hẹn gặp lại anh em ở Bài 36: Đặc tính cơ bản của kế thừa đơn (Phần 2) - Cú lừa của private và sự xuất hiện của protected! Nhớ thả Upvote để tiếp lửa cho series nhé!

📚 Nguồn: Viblo

Bình luận

0 bình luận

Email không hiển thị công khai.

Chưa có bình luận nào. Hãy là người đầu tiên bình luận.

Chia sẻ bài viết

Cần tư vấn?

Liên hệ với chúng tôi để được hỗ trợ

Liên hệ ngay

Bài viết liên quan

Giải Mã Từ Khóa super Trong JavaScript: "Chiếc Cầu Nối" Đến Lớp Cha Và Cú Vấp Bắt Buộc Trước Khi Chạm Vào this
28/06/2026

Giải Mã Từ Khóa super Trong JavaScript: "Chiếc Cầu Nối" Đến Lớp Cha Và Cú Vấp Bắt Buộc Trước Khi Chạm Vào this

Chào anh em Viblo! 👋 Khi thế giới JavaScript chuyển mình lên chuẩn ES6, cú pháp Class (Lớp) ra đời đã thay đổi hoàn toàn cách chúng ta viết code theo tư duy Lập trì...

Đọc thêm
Vén Màn Bí Mật var require: NodeRequire;: Hàm require Của Node.js Khủng Khiếp Hơn Bạn Nghĩ!
28/06/2026

Vén Màn Bí Mật var require: NodeRequire;: Hàm require Của Node.js Khủng Khiếp Hơn Bạn Nghĩ!

Chào anh em Viblo! 👋 Nếu anh em đã từng làm việc với Node.js ở kỷ nguyên CommonJS, hoặc đang cấu hình các file script, file webpack, vite trong các dự án hiện đại, ...

Đọc thêm
Giải Mã var __dirname: string;: Tấm Bản Đồ Định Vị File Và Cú Vấp Ngã Xuyên Quốc Gia Giữa Windows và Linux
28/06/2026

Giải Mã var __dirname: string;: Tấm Bản Đồ Định Vị File Và Cú Vấp Ngã Xuyên Quốc Gia Giữa Windows và Linux

Chào anh em Viblo! 👋 Tiếp nối chuỗi bài viết mổ xẻ các tham số "quyền lực" được tiêm (inject) ngầm vào bên trong Module Wrapper Function của Node.js (sau khi chúng ...

Đọc thêm

Bắt đầu dự án của bạn

Hãy để Flash Dev đồng hành cùng bạn

Liên hệ ngay