Hỏi Đáp

Khái Niệm Kế Thừa Là Gì – Từ Điển Tiếng Việt Kế Thừa

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.

Đang xem: Kế thừa là gì

Để đọc hiểu bài này tốt 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 một ít thời gian đọc bài viết về class của mình. Nếu bạn đã sẵn sàng thì hãy bắt đầu thôi!

*
*
*

Sơ đồ Class

Vậy là chúng ta đã tìm hiểu xong các loại 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 đó, class cha và class con đã được trình bày ở bên trên, phạm vi truy cập sẽ được mình trình bày ngay bến dưới.

Giả sử mình có một class A với các thuộc tính, phương thức bên trong. Mình muốn khai báo một class B kế thừa từ class 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 class A sẽ được class B kế thừa. public/private/protected 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 xem cụ thể phạm vi truy cập là 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 (access modifier). 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 class cha từ class 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ề Class 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ó class B kế thừa từ class A, cụ thể các phạm vi truy cập đó là như sau:

public:Các thuộc tính public của A sẽ trở thành thuộc tính public của BCác thuộc tính protected của A sẽ trở thành protected của Bprivate:Các thuộc tính public của A sẽ trở thành thuộc tính private của BCác thuộc tính protected của A sẽ trở thành private của Bprotected:Các thuộc tính public của A sẽ trở thành thuộc tính protected của BCác thuộc tính protected của A sẽ trở thành thuộc tính protected của B

Đối với một class, thuộc tính protected cũng tương tự như private, chỉ có khác ở chỗ class con có thể truy cập thành phần protected, còn private lại không cho phép truy cập.

Xem thêm: Cú Pháp Chuyển Tiền Vinaphone, 2 Cách Bắn Tiền Vinaphone Đơn Giản Nhất

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 ở class cha, được kế thừa private sang class con, thì nó cũng trở thành private ở class con và không thể được truy cập từ bên ngoài class con. Ví dụ:

class A{public: int publicMethod;};class B : private A{};// bên trong hàm mainB b;cout

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ả. Để cho 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++. Hãy bắt đầu với 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 class con kế thừa thành phần từ class cơ sở, các thành phần của nó cũng sẽ được thừa hưởng từ class cơ sở. Điều này có nghĩa là, bạn có thể sử dụng con trỏ this để thao tác với thành phần của class hiện tại như bình thường. Ví dụ:

class A{public: int count; void sayHello() { cout 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 }};

Override 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 ở class con và class 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 ở class con sẽ ghi đè lên phương thức ở class cha và thay thế hoàn toàn nó. Ví dụ:

class A{public: void sayHello() { cout Vậy thì 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 đè, vậy thì không còn đảm bảo được tính tái sử dụng code của tính kế thừa. Vậy làm sao chúng ta có thể tái sử dụng lại đoạn code của phương thức ở class cha?

Sử dụng toán tử phân giải phạm vi (::), chúng ta có thể gọi được phương thức từ class cha, ngoài ra chúng ta còn có thể bổ sung được những đoạn code của riêng phương thức ở class con. Ví dụ:

class A{public: void sayHello() { cout Thật đơn giản đúng không nào!

Upcasting và downcasting

Nhiều bạn có thể sẽ thắc mắc, ví dụ “sinh viên là một 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 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 là chuyển đổi đối tượng kiểu class con sang kiểu class cha. Tức là, con trỏ kiểu class cha có thể trỏ đến con trỏ kiểu class con, nhưng không bảo toàn được những thuộc tính, phương thức của class con. Việc chuyển kiểu này được thực hiện ngầm định bởi trình biên dịch C++. Các phương thức bị override sẽ bị override ngược lại bởi class cha. Ví dụ:

class A{public: void sayHello() { cout sayHello(); // Hello, welcome to khiemle.dev!p->sayGoodbye(); // Lỗi do A không có phương thức nàyRõ ràng, nếu như sinh viên là một 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 class cha là class tổng quát hóa, có ít thông tin hơn so với class con, do đó, khi chuyển kiểu ta không thể đảm bảo sự toàn vẹn dữ liệu được.

Downcasting

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

class A{public: void sayHello() { cout propInB = 0; } void sayHello() { A::sayHello(); cout propInB; // Một số ngẫu nhiên

Đa kế thừa

Đa kế thừa nghĩa là thay vì một class dẫn xuất kế thừa từ một class cơ sở, class dẫn xuất này có thể có kế thừa từ nhiều class cơ sở khác nhau. Ví dụ như một loài động vật thì sẽ kế thừa đặ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 class cơ sở có thể có nhiều hơn 1, ngăn cách nhau bởi dấu phẩy (,). Ví dụ:

class A {public: A() {}};class B {public: B() {}};// Class C kế thừa từ class A và Bclass C : public A, public B {public: C() {}};Khi thừa kế từ nhiều class cơ sở, bạn thấy sẽ có 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 sự mơ hồ. Sự mơ hồ nghĩa là trình biên dịch không biết bạn đang gọi phương thức từ class dẫn xuất nào. Ví dụ:

class A {public: A() {} void sayHello() { cout Để giải quyết sự nhập nhằn này, bạn có thể sử dụng toán tử phạm vi (::) để chỉ rõ phương thức ở class nào như sau:

class A {public: A() {} void sayHello() { cout

Tổng kết

Trong phần kế thừa này, cơ bản nó không khó, chỉ cần bạn phân tích đặc tả được 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 bài tập về phần này để các bạn nắm được về kế thừa trong C++.

Xem thêm: Cách Làm Gừng Chua Kiểu Nhật, Làm Gừng Muối Gari Kiểu Nhật Bản

Vậy 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 thấy bài viết của mình, đừng quên chia sẻ cho bạn bè cùng biết nha.

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

Related Articles

Trả lời

Email của bạn sẽ không được hiển thị công khai.

Back to top button