Được bảo vệ trong C++

Kế thừa trong lập trình hướng đối tượng là một tính chất rất quan trọng, do đó, các bạn nên nắm kỹ phần này để có thể học tốt lập trình hướng đối tượng. Trong các kỳ kiểm tra, phỏng vấn xin việc cũng thường được hỏi về tính chất này

Để đọc hiểu bài viết này hay nhất, các bạn nên có biến thức Cơ bản về class trong C++, nếu chưa hãy dành ít thời gian đọc bài viết về class của mình. Nếu bạn đã có sẵn thì hãy bắt đầu thôi

Được bảo vệ trong C++
Được bảo vệ trong C++

  1001 Mẹo. Con trỏ và hàm (Con trỏ & Hàm) trong C++

  Bảng băm trong C++

Kế thừa là gì?

Kế thừa là một trong các tính chất đặc trưng của chương trình hướng đối tượng, bên cạnh tính đóng gói (đóng gói), che giấu thông tin (giấu thông tin), tính đa hình (đa hình) và tính trừu tượng (trừu tượng). Vậy thì kế thừa là gì?

Kế thừa (kế thừa) là một tính chất đặc trưng của hướng đối tượng lập trình. Nó có nghĩa là một lớp thừa hưởng lại tất cả các thuộc tính, phương thức của lớp mà nó kế thừa

Lớp kế thừa từ một lớp khác được gọi là lớp con (lớp con hoặc lớp con) hoặc lớp dẫn xuất (lớp dẫn xuất). Lớp được lớp khác kế thừa được gọi là lớp cha (lớp cha hay lớp cha) hay lớp cơ sở (lớp cơ sở)

Ví dụ như bạn có một lớp con người, có các thuộc tính cơ bản như họ tên, ngày sinh, quê quán, mình khai báo thêm một lớp sinh viên kế thừa từ lớp con người. Vì vậy, lớp sinh viên sẽ có các thuộc tính họ tên, ngày sinh, quê quán từ lớp con người mà không cần phải khai báo. Lớp con người sẽ là lớp cha và lớp sinh viên là lớp con

Ngoài các thuộc tính của lớp cha, lớp con còn có thể có thêm các thuộc tính, phương thức của riêng mình. Ví dụ như sinh viên thì có thêm các thuộc tính như MSSV, tên trường, chuyên ngành…

Được bảo vệ trong C++
Được bảo vệ trong C++
Kế thừa kế thừa

Chúng ta đã hiểu được kế thừa là gì rồi. Do đó, câu hỏi đặt ra lúc này là tại sao cần phải có kế thừa?

Tại sao cần phải có kế thừa?

Trong quá trình lập trình, chắc chắn các bạn sẽ gặp phải rất nhiều hành động lặp đi lặp lại, và chắc chắn một điều rằng sẽ không ai rảnh mà ngồi code lại từ đầu cả. Thay vào đó, họ sẽ sử dụng lại các đoạn mã đã có để thực hiện công việc tương tự. Nói đến đây chắc các bạn cũng đã hiểu kế thừa có tác dụng gì rồi đúng không nào

Kế thừa giúp ta có thể tái sử dụng lại các đoạn mã đã có, tránh việc giải quyết các bài toán con đã có lời giải trước đó, gây lãng phí thời gian. Nếu chỉ là một, hai hoặc ba hành động cần giải quyết thì không thành vấn đề, nhưng nếu là một phần trăm thì đó lại là một chuyện khác, bạn sẽ mất thời gian nếu bạn không biết tận hưởng những gì đã có đó.

Trong ví dụ ở đầu bài viết, các bạn có để ý thấy mối quan hệ giữa giai cấp con người và sinh viên không? . Do đó, tính kế thừa giúp chúng ta có thể dễ dàng thể hiện mối quan hệ giữa các đối tượng hơn (sẽ được trình bày bên dưới)

Sinh viên ngoài những điểm đặc biệt của lớp con người ra, còn có thể có thêm những điểm đặc biệt của riêng mình ví dụ như tên trường, tên ngành, năm học… Đây là mối quan hệ tổng lược hóa – đặc biệt hóa trong kế hoạch . Lớp con người chính là tổng tiêu hóa và lớp con viên chính là đặc biệt hóa

Mối quan hệ giữa các đối tượng

Có hai mối quan hệ giữa các đối tượng trong C++, quan hệ “Has-A” và quan hệ “Is-A”

Quan hệ Has-A

Có 3 loại quan hệ “có” giữa các đối tượng, mối quan hệ một – một, mối quan hệ một – nhiều và mối quan hệ nhiều – nhiều

Quan hệ một – một (1 – 1) là mối quan hệ giữa hai đối tượng thuộc hai lớp khác nhau, mỗi đối tượng thuộc lớp này có quan hệ duy nhất với một đối tượng thuộc lớp kia và tương ứng với từng đối tượng của lớp.

Ví dụ như mỗi lớp chỉ có một giáo viên chủ nhiệm, mỗi giáo viên chỉ được chủ nhiệm một lớp, mỗi một quốc gia chỉ có một thủ đô, một thành phố chỉ có thể là thủ đô của một quốc gia…

Quan hệ một – nhiều (1 – n) là mối quan hệ giữa các đối tượng thuộc hai lớp khác nhau, mỗi đối tượng thuộc lớp này có quan hệ duy nhất với một đối tượng thuộc lớp kia, nhưng mỗi đối tượng thuộc lớp kia có

Ví dụ như mỗi học sinh chỉ có một lớp học, nhưng mỗi lớp học lại có thể có nhiều học sinh, hay mỗi nhân viên chỉ có thể làm cho một công ty nhưng một công ty lại có thể có nhiều nhân viên…

Quan hệ nhiều – nhiều (n – n) là mối quan hệ giữa các đối tượng thuộc hai lớp khác nhau, mỗi đối tượng thuộc lớp này có thể quan hệ với nhiều đối tượng thuộc lớp kia, và mỗi đối tượng thuộc lớp kia cũng có

Ví dụ như mỗi bệnh nhân có thể khám bệnh ở nhiều bác sĩ khác nhau, và mỗi bác sĩ lại có thể khám bệnh cho nhiều bệnh nhân…

Quan hệ tổng thể – đặc biệt hóa là mối quan hệ giữa các đối tượng thuộc hai lớp khác nhau khi đối tượng thuộc lớp này là trường hợp đặc biệt của lớp kia, và đối tượng thuộc lớp kia là trường tổng hợp của đối tượng

Ví dụ như con người là tổng hợp hóa của sinh viên, còn sinh viên là đặc biệt hóa của con người, xe máy hiệu exciter là đặc biệt hóa của xe máy và xe máy là tổng hợp của xe máy hiệu exciter…

Quan hệ Is-A

Mối quan hệ Is-A giữa các đối tượng chính là lớp này là lớp kia. Cũng ví dụ từ đầu bài viết đến giờ, sinh viên là một kẻ lừa đảo (sinh viên là con người). Đó chính là mối quan hệ đã được thực hiện kế thừa

Các loại kế thừa

Chúng ta đã cùng nhau tìm hiểu về kế thừa là gì và tại sao cần phải có kế thừa, tiếp theo, hãy cùng tìm hiểu xem có những loại kế thừa nào nha

Kế thừa đơn

Kế thừa đơn (kế thừa đơn) là một lớp kế thừa duy nhất từ ​​một lớp cha. Ví dụ như lớp sinh viên chỉ kế thừa duy nhất từ ​​lớp con người, đó là kế thừa đơn

Được bảo vệ trong C++
Được bảo vệ trong C++
kế thừa đơn vị

Kế hoạch đa cấp

Kế thừa đa cấp (kế thừa đa cấp) là một lớp kế thừa từ một lớp cha, lớp cha đó lại kết thừa từ một lớp khác. Ví dụ như lớp sinh viên kế thừa từ lớp học sinh, lớp học sinh lại kế thừa từ lớp con người, đó là kế thừa đa cấp

Được bảo vệ trong C++
Được bảo vệ trong C++
Kế hoạch đa cấp

Kế hoạch phân cấp kế thừa

Kế thừa phân cấp (thừa kế phân cấp) là khi có nhiều hơn một lớp kế thừa từ lớp cha. Ví dụ như lớp sinh viên và lớp công nhân đều kế thừa từ lớp cha là con người

Được bảo vệ trong C++
Được bảo vệ trong C++
Kế hoạch phân cấp kế thừa

Một sơ đồ lớp không chỉ có một trong 3 loại kế thừa, mà thậm chí có thể có cả 3 và điều này hoàn toàn bình thường và rất thường xuyên

Được bảo vệ trong C++
Được bảo vệ trong C++
Class sơ đồ

Do đó chúng ta đã tìm hiểu xong các kiểu kế thừa, giờ hãy xem cú pháp thực hiện kế thừa trong C++ như thế nào

cú pháp

Cú pháp để khai báo một lớp kế thừa từ một lớp như sau

class  :  
{
    // code goes here
};

Trong đó, lớp cha và lớp con đã được trình bày ở bên trên, phạm vi truy cập sẽ được trình bày ngay bến dưới

Giả sử mình có một lớp A với các thuộc tính, phương thức bên trong. Mình muốn khai báo lớp B kế thừa từ lớp A, mình sẽ có cú pháp như sau

class B : public/private/protected A
{
    // code goes here
};

Khi này, các thuộc tính trong lớp A sẽ được lớp B kế thừa. công khai/riêng tư/được bảo vệ là phạm vi truy cập của các thuộc tính sẽ được kế thừa. Hãy cùng tìm hiểu cụ thể phạm vi truy cập như thế nào ngay bên dưới

Phạm vi truy cập

Trong bài Cơ bản về Class trong C++ mình đã có giới thiệu qua về phạm vi truy cập (công cụ sửa đổi truy cập). Tuy nhiên, phạm vi truy cập trong bài đó khác với phạm vi truy cập trong kế thừa

Có hai loại phạm vi truy cập, truy cập các thành phần từ bên ngoài đối tượng được gọi là truy cập theo chiều ngang. Truy cập các thành phần của lớp cha từ lớp con được gọi là truy cập theo chiều dọc. Phạm vi truy cập trong bài Cơ bản về Lớp trong C++ chính là truy cập theo chiều ngang

Đối với phạm vi truy cập trong kế thừa, đó là truy cập theo chiều dọc. Giả sử mình có lớp B kế thừa từ lớp A, cụ thể các phạm vi truy cập đó là như sau

  • công cộng
    • Thuộc tính public của A sẽ trở thành thuộc tính public của B
    • Các thuộc tính được bảo vệ của A sẽ trở thành thuộc tính được bảo vệ của B
  • riêng
    • Thuộc tính public của A sẽ trở thành thuộc tính private của B
    • Các thuộc tính được bảo vệ của A sẽ trở thành riêng tư của B
  • được bảo vệ
    • Thuộc tính public của A sẽ trở thành thuộc tính được bảo vệ của B
    • Thuộc tính được bảo vệ của A sẽ trở thành thuộc tính được bảo vệ của B

Được bảo vệ trong C++
Được bảo vệ trong C++
Phạm vi truy cập trong kế thừa C++

Đối với một lớp, thuộc tính được bảo vệ cũng tương tự như riêng tư, chỉ có khác ở chỗ con lớp có thể truy cập vào phần được bảo vệ, còn riêng tư lại không cho phép truy cập

Phạm vi truy cập giúp đảm bảo tính đóng gói và che giấu thông tin của đối tượng. Ví dụ như khi thuộc tính public ở lớp cha, được kế thừa private sang lớp con, thì nó cũng trở thành private ở lớp con và không thể truy cập được từ bên ngoài lớp con. Ví dụ

class A
{
public:
    int publicMethod;
};

class B : private A
{
};

// bên trong hàm main
B b;
cout << b.publicMethod; // lỗi vì lúc này publicMethod trở thành private method của B rồi

Cài đặt

Từ đầu bài viết đến giờ, mình nói khá nhiều về lý thuyết mà chưa có đoạn code nào cả. Để các bạn dễ hiểu hơn, mình sẽ sử dụng lại các ví dụ trong bài viết và code chúng bằng C++. Please started with các quan hệ Has-A trước

Quan hệ 1 – 1

class GVCN
{
public:
    LopHoc lopHoc;
};

class LopHoc
{
public:
    GVCN gvcn;
};

Bạn nào chưa biết về vector có thể xem lại bài viết Vector trong C++ của mình nha

Quan hệ 1 – n

class HocSinh
{
public:
    LopHoc lopHoc;
};

class LopHoc
{
public:
    vector hocSinh;
};

quan hệ n – n

class BenhNhan
{
public:
    vector bacSi;
};

class BacSi
{
public:
    vector benhNhan;
};

Quan hệ Is-A

class ConNguoi
{
public:
    string hoTen;
    string ngaySinh;
    string queQuan;
};

class SinhVien : public ConNguoi
{
public:
    string MSSV;
    string tenTruong;
    string lop;
    string chuyenNganh;
};

Truy xuất thành phần từ lớp cơ sở

Khi lớp kế thừa thành phần từ cơ sở lớp, các thành phần của nó cũng sẽ được thừa hưởng từ cơ sở lớp. Điều này có nghĩa là, bạn có thể sử dụng con trỏ này để thao tác với thành phần của lớp hiện tại như bình thường. Ví dụ

class A
{
public:
    int count;

    void sayHello()
    {
        cout << "Hello, welcome to KhiemLe.Dev!";
    }
};

class B : public A
{
public:
    B() // constructor
    {
        this->count = 0; // thuộc tính count được kế thừa và có thể truy cập qua con trỏ this
        this->sayHello(); // phương thức cũng được kế thừa
    }
};

Ghi đè phương thức từ lớp cơ sở

Trong khi sử dụng tính kế thừa, bạn sẽ gặp phải trường hợp hai phương thức ở lớp con và lớp cha trùng tên nhau. Trong trường hợp này, phương thức được khai báo và định nghĩa ở lớp con sẽ ghi đè lên phương thức ở lớp cha và thay thế hoàn toàn nó. Ví dụ

________số 8

Do đó, bạn có thể thấy được là, nếu như mà phương thức bị trùng tên thì nó bị ghi lại, vậy thì không còn chắc chắn được tính tái sử dụng mã của tính kế thừa. Vậy thì sao chúng ta có thể tái sử dụng lại đoạn mã của phương thức ở lớp cha?

Sử dụng thuật toán phân tích phạm vi (. ), chúng ta có thể gọi là phương thức thức từ lớp cha, ngoài ra chúng ta còn có thể bổ sung được các đoạn mã của phương thức riêng ở lớp con. Ví dụ

class A
{
public:
    void sayHello()
    {
        cout << "Hello, welcome to khiemle.dev!";
    }
};

class B : public A
{
public:
    void sayHello()
    {
        A::sayHello(); // Gọi lại phương thức ở class A
        // Thêm các đoạn code các bạn muốn
        cout << endl;
        cout << "Nho like va share nha ^^!";
    }
};

// trong hàm main
B b;
b.sayHello();
// Hello, welcome to khiemle.dev!
// Nho like va share nha ^^!

Đơn giản không đúng sự thật

Upcasting và downcasting

Nhiều bạn có thể sẽ thắc mắc, ví dụ ví dụ “sinh viên là con người”, vậy thì con trỏ kiểu sinh viên có thể trỏ đến con trỏ kiểu con người hoặc ngược lại hay không. Đây chính là vấn đề upcasting và downcasting. Tuy nhiên, để đảm bảo tính toàn vẹn dữ liệu, bạn chỉ nên xem tham khảo chứ không nên sử dụng, do có thể gây mất mát dữ liệu hoặc nhận dữ liệu không mong muốn

Upcasting

Upcasting is convert object type class con to type class cha. Tức là, con trỏ kiểu lớp cha có thể trỏ đến con trỏ kiểu lớp con, nhưng không đảm bảo toàn bộ các thuộc tính, phương thức của lớp con. Kiểu chuyển đổi này đã được giải quyết bởi biên dịch C++. The method are override will be override back by class cha. Ví dụ

class B : public/private/protected A
{
    // code goes here
};
0

Rõ ràng, nếu như sinh viên là con người, thì con trỏ kiểu con người có thể lưu trữ được sinh viên đúng không bởi vì sinh viên là con người mà

Tuy nhiên, do lớp cha là lớp tổng hợp hóa, có ít thông tin hơn so với lớp con, do đó, khi chuyển kiểu ta không thể đảm bảo toàn bộ dữ liệu được

hạ thấp

Downcasting thì ngược lại với upcasting, tức là chuyển đối tượng kiểu lớp cha sang đối tượng kiểu lớp con. Cách này lại không được biên dịch thực hiện tự động mà bạn phải tự chuyển đổi kiểu của nó. Tuy nhiên, các thuộc tính, phương thức ở lớp con nhiều hơn lớp cha, do lớp con là cụ thể hóa của lớp cha. Do đó, các thuộc tính không có ở lớp cha sẽ nhận được giá trị rác không mong muốn. Ví dụ

class B : public/private/protected A
{
    // code goes here
};
1

Kế thừa

Kế thừa nghĩa là thay vì một lớp dẫn xuất kế thừa từ một cơ sở lớp, lớp dẫn xuất này có thể có kế thừa từ nhiều cơ sở lớp khác nhau. Ví dụ như một loài động vật thì sẽ kế thừa những đặc điểm từ cả bố và mẹ của chúng

Trong C++, để thực hiện đa kế thừa, cú pháp tương tự như kế thừa, nhưng cơ sở hạ tầng lớp có thể có nhiều hơn 1, ngăn cách nhau bởi dấu phẩy (,). Ví dụ

class B : public/private/protected A
{
    // code goes here
};
2

Khi kế thừa từ nhiều lớp cơ sở, bạn sẽ thấy một vấn đề phát sinh chính là khi lớp cơ sở có phương thức trùng tên, khi gọi phương thức sẽ xảy ra mơ hồ. Sự thật về mơ hồ là trình biên dịch mà bạn không biết bạn đang gọi phương thức từ lớp dẫn xuất nào. Ví dụ

class B : public/private/protected A
{
    // code goes here
};
3

Để giải quyết vấn đề này, bạn có thể sử dụng thuật toán phạm vi (. ) to known method at class any as after

class B : public/private/protected A
{
    // code goes here
};
4

Tổng kết

Trong phần kế thừa này, cơ bản của nó không khó, chỉ cần bạn phân tích đặc tả dữ liệu mà đề bài cho, hoặc trong tình huống thực tế, bạn sẽ làm được nó. Trong thời gian tới mình sẽ cố gắng tổng hợp các bài tập về phần này để các bạn nắm bắt được kế thừa trong C++

Vì thế là qua bài này, mình đã giới thiệu cho các bạn biết về kế thừa trong C++ nói riêng và trong lập trình hướng đối tượng nói chung. Hi vọng là các bạn đã thấy bài viết của mình đừng quên chia sẽ cho các bạn cùng biết nha

Nếu có bất kỳ thắc mắc hay đóng góp ý kiến ​​nào, các bạn có thể comment phía dưới bài viết. Cảm ơn các bạn đã đọc bài viết