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óm Tắt
Tính đa hình là gì ?
Sự thừa kế trong C + + được cho phép có sự tương ứng giữa lớp cơ sở và những 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.
Bạn đang xem:
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.Bạn đang xem: Polymorphism là gì
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 người tiêu dùng lớp Mayvitinh :
mayAcer may1; Mayvitinh *tenmay = &may1tenmay->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.Compile time Polymorphism. Runtime Polymorphism .
1. Compile time 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àmNạ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ố.
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ó tác dụng :
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.
Xem thêm: Chuyên Mục Cuộc Sống: Tình Cảm Gia Đình Là Gì ? Có Ý Nghĩa Gì? Vai Trò Ra Sao
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ó những phương pháp giám sát 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 những phương pháp trên khá khó khăn vất vả và hoàn toàn có thể gây rối cho người lập trình. Vì thế ta sẽ nạp chồng lại những toán tử để hoàn toàn có thể tạo một cái nhìn trực quan vào code, giảm thiểu những lỗi sai không đáng có .Các toán tử hoàn toàn có thể nạp chồng
Các toán tử không hề 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 và 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 hiệu 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:2. Runtime Polymorphism :Các bàn còn nhớ ví dụ tiên phong 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 pháp show ( ) của lớp Mayvitinh, mà không gọi tới phương pháp show ( ) của lớp mayAcer .Vậy để chương trình gọi tới phương pháp 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ó hiệu 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 người tiêu dù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 tác dụng 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
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: Các Kiểu Môi Trường Của Đới Ôn Hòa Là Gì? Định Nghĩa, Khái Niệm
Nếu những bạn có vướng mắc hay câu hỏi gì hoàn toàn có thể comment và rate bên dưới bài viết. Mình kỳ vọng sẽ nhận được sự ủng hộ của những bạn trong những bài khác với chủ đề khác.
Source: https://final-blade.com
Category : Kiến thức Internet