Trong bài trước, chúng ta hiểu được thế nào làtính kế thừatrong OOP. Ở bài này chúng ta sẽ tìm hiểu thêm một tính chất nữa của lập trình hướng đối tượng đó là tính đa hình nhé.

Bạn đang xem: Polymorphism là gì

Tính đa hình là gì ?

Sự kế thừa trong C++ cho phép có sự tương ứng giữa lớp cơ sở và các lớp dẫn xuất trong sơ đồ thừa kế:

Một con trỏ có kiểu lớp cơ sở luôn có thể trỏ đến địa chỉ của một đối tượng của lớp dẫn xuất.Tuy nhiên, khi thực hiện lời gọi một phương thức của lớp, trình biên dịch sẽ quan tâm đến kiểu của con trỏ chứ không phải đối tượng mà con trỏ đang trỏ tới: phương thức của lớp mà con trỏ có kiểu được gọi chứ không phải phương thức của đối tượng mà con trỏ đang trỏ tới được gọi.

Ví dụ:Lớp mayAcer kế thừa từ lớp Mayvitinh, cả hai lớp này đều định nghĩa phương thức show()

class Mayvitinh{ public: void show(){ cout khi đó, nếu ta khai báo một con trỏ lớp mayAcer, nhưng lại trỏ vào địa chỉ của một đối tượng lớp Mayvitinh:

mayAcer may1; Mayvitinh *tenmay = &may1;tenmay->show(); thì chương trình sẽ gọi đến phương thức show() của lớp Mayvitinh, mà không gọi tới phương thức show() của lớp mayAcer.Để giải quyết vấn đề này, chúng ta cần sử dụng đến tính đa hình trong Lập trình hướng đối tượng. Mình sẽ giải thích chi tiết hơn ở bên dưới.

Đa hình (polymorphism)nghĩa là có nhiều hình thái khác nhau. Tiêu biểu là, đa hình xuất hiện khi có một cấu trúc cấp bậc của các lớp và chúng liên quan với nhau bởi tính kế thừa.

Mình lấy một ví dụ thực thế nhé:Một người cùng một lúc có thể có đặc điểm khác nhau. Giống như một người đàn học sinh thời là một người con trai, một người bạn, một người anh. Vì vậy, cùng một người sở hữu những hành vi khác nhau trong các tình huống khác nhau. Điều này được gọi là đa hình.

Đa hình được coi là một trong những tính năng quan trọng của Lập trình hướng đối tượng.

Các loại đa hình:

Tính đa hình chủ yếu được chia thành hai loại:

Compile time Polymorphism.Runtime Polymorphism.

*

1. Compile time Polymorphism:

Tính đa hình này được sử dụng bằng cách nạp chồng hàm hoặc nạp chồng toán tử.

Vậy nạp chồng hàm và nạp chồng toán tử là gì?

Nạp chồng hàm

Nạp chồng hàm (Function Overloading)cho phép sử dụng cùng một tên gọi cho các hàm “giống nhau” (có cùng mục đích). Nhưng khác nhau về kiểu dữ liệu tham số hoặc số lượng tham số.

Nạp chồng hàm cho phép ta khai báo và định nghĩa các hàm trên cùng với một tên gọi.

Xem thêm: Huyết Áp Tâm Trương Là Gì – Bệnh Viện Nguyễn Tri Phương

Chúng ta lấy ví dụ:

#include using namespace std; class inDuLieu { public: void hamIn(int i) { cout Biên dịch chương trình ta có kết quả:

Trong ví dụ trên, ta chỉ dùng một hàm duy nhất có tên làhamIn()nhưng có thể dùng được cho 3 tình huống khác nhau. Đây là một thể hiện của tính đa hình.

Nạp chồng toán tử

Nạp chồng toán tử (Operator Overloading) được dùng để định nghĩa toán tử cho có sẵn trong c++ phục vụ cho dữ liệu riêng do bạn tạo ra.

Giả sử có lớpPhanSovà có các phương thức tính toán như Cong, Tru, Nhan, Chia.Nếu gặp một biểu thức phức tạp, số lượng phép tính nhiều thì việc sử dụng các phương thức trên khá khó khăn và có thể gây rối cho người lập trình. Vì thế ta sẽ nạp chồng lại các toán tử để có thể tạo một cái nhìn trực quan vào code, giảm thiểu các lỗi sai không đáng có.

Các toán tử có thể nạp chồng

*

Các toán tử không thể nạp chồng:

..*::?:

Ví dụ:

#include using namespace std;class Box{ public: double tinhTheTich(void) { return chieudai * chieurong * chieucao; } void setChieuDai( double dai ) { chieudai = dai; } void setChieuRong( double rong ) { chieurong = rong; } void setChieuCao( double cao ) { chieucao = cao; } // Nap chong toa tu + de cong hai doi tuong Box. Box operator+(const Box& b) { Box box; box.chieudai = this->chieudai + b.chieudai; box.chieurong = this->chieurong + b.chieurong; box.chieucao = this->chieucao + b.chieucao; return box; } private: double chieudai; // chieu dai cua mot box double chieurong; // Chieu rong cua mot box double chieucao; // Chieu cao cua mot box};// ham main cua chuong trinhint main( ){ Box Box1; // Khai bao Box1 la cua kieu Box Box Box2; // Khai bao Box2 la cua kieu Box Box Box3; // Khai bao Box3 la cua kieu Box double thetich = 0.0; // Luu giu the tich cua mot box tai day // thong tin chi tiet cua box 1 Box1.setChieuDai(5); Box1.setChieuRong(2); Box1.setChieuCao(4); // thong tin chi tiet cua box 2 Box2.setChieuDai(7); Box2.setChieuRong(6); Box2.setChieuCao(9); // the tich cua box 1 thetich = Box1.tinhTheTich(); cout Sau khi chạy chương trình cho kết quả:

Trong ví dụ trên, ta đã nạp chồng lại toán tử cộng. Tính đa hình được thể hiện qua việc nạp chồng để tính tổng Box1 và Box2.

2. Runtime Polymorphism:

Các bàn còn nhớ ví dụ đầu tiên của bài không.

#include using namespace std;class Mayvitinh{ public: void show(){ cout show(); }Có thể thấy chương trình sau khi chạy sẽgọi đến phương thức show() của lớp Mayvitinh, mà không gọi tới phương thức show() của lớp mayAcer.

Vậy để chương trình gọi tới phương thức show() của lớp mayAcer ta sử dụng hàm ảo virtual như sau:

#include using namespace std;class Mayvitinh{ public: virtual void show(){ cout show(); }Sau khi biên dịch chương trình sẽ có kết quả:

Trong ví dụ trên mình đã thêm từ khóavirtualvào hàmshow()trong lớp cơ sởMayvitinh.Từ khóavirtualnày dùng để khai báo một hàm là hàm ảo.

Khi khai báo hàm ảo với từ khóavirtualnghĩa là hàm này sẽ được gọi theo loại đối tượng được trỏ (hoặc tham chiếu), chứ không phải theo loại của con trỏ (hoặc tham chiếu). Và điều này dẫn đến kết quả khác nhau:

Nếu không khai báo hàm ảovirtualtrình biên dịch sẽ gọi hàm tại lớp cở sởNếu dùng hàm ảovirtualtrình biên dịch sẽ gọi hàm tại lớp dẫn xuất

Khi nhận thấy có khai báovirtualtrong lớp cơ sở, trình biên dịch sẽ thêm vào mỗi đối tượng của lớp cơ sở và các lớp dẫn xuất của nó một con trỏ chỉ đến bảng phương thức ảo (virtual function table). Con trỏ đó có tên là vptr (virtual pointer). Bảng phương thức ảo là nơi chứa các con trỏ chỉ đến đoạn chương trình đã biên dịch ứng với các phương thức ảo. Mỗi lớp có một bảng phương thức ảo. Trình biên dịch chỉ lập bảng phương thức ảo khi bắt đầu có việc tạo đối tượng của lớp. Đến khi chương trình chạy, phương thức ảo của đối tượng mới được nối kết và thi hành thông qua con trỏ vptr.

Kết

Vậy là series Lập trình hướng đối tượng của mình đến đây là kết thúc, chúng ta đã được tìm hiểu các khái niệm xoay quanh OOP trong C++ và những tính chất quan trọng của nó. Mình hy vọng bài viết của mình sẽ một phần giúp các ban trong việc học tập lập trình, đặc biệt là tìm hiểu về OOP.

Xem thêm: 2013 Là Năm Con Gì – 2013 Hợp Hướng Nào

Nếu các bạn có thắc mắc hay câu hỏi gì có thể comment và rate bên dưới bài viết. Mình hy vọng sẽ nhận được sự ủng hộ của các bạn trong những bài khác với chủ đề khác.

Chuyên mục: Hỏi Đáp