TÍNH ĐA HÌNH LÀ GÌ

     

Đa hình là gì?

Đa hình là 1 trong bốn đặc điểm đặc trưng của lập trình hướng đối tượng sát bên tính đóng gói, tính trừu tượng và tính kế thừa. Vậy thì đa hình là gì?

Đa hình (polymorphism) là hiện tượng kỳ lạ mà các đối tượng người tiêu dùng thuộc những class khác nhau hoàn toàn có thể biểu diễn cùng một thông thiệp theo các cách khác nhau. Khá nặng về lý thuyết một chút nhưng lại xem lấy ví dụ sau bạn sẽ rõ ngay!


*
Sơ đồ vật Class

Dựa trên sơ đồ vẫn xây dựng, mình đang code những class như sau:

class NhanVienprotected: string hoTen; float luong;public: NhanVien() this->hoTen = ""; this->luong = 0.0; void nhap() cout hoTen); void xuat() cout hoTen class NhanVienSanXuat : public NhanVienprivate: int soSanPham; float tienCong1SP;public: NhanVienSanXuat() : NhanVien() this->soSanPham = 0; this->tienCong1SP = 0; void nhap() NhanVien::nhap(); cout > this->soSanPham; cout > this->tienCong1SP; void xuat() cout soSanPham tienCong1SP luong luong = this->soSanPham * this->tienCong1SP; ;class NhanVienVanPhong : public NhanVienprivate: float luongCoBan; int soNgayLamViec;public: NhanVienVanPhong() : NhanVien() this->luongCoBan = 0.0; void nhap() NhanVien::nhap(); cout > this->luongCoBan; cout > this->soNgayLamViec; void xuat() NhanVien::xuat(); cout luongCoBan soNgayLamViec luong luong = this->soNgayLamViec * this->luongCoBan; ;class CongTyprivate: vector NVVP; vector NVSX;public: void nhap() cout > n; for (int i = 0; i NVVP.push_back(nv); cout > m; for (int i = 0; i NVSX.push_back(nv); void xuat() cout NVVP.size(); i++) cout NVVP.at(i).xuat(); cout NVSX.size(); i++) cout NVSX.at(i).xuat(); void tinhLuong() for (int i = 0; i NVVP.size(); i++) this->NVVP.at(i).tinhLuong(); for (int i = 0; i NVSX.size(); i++) this->NVSX.at(i).tinhLuong(); ;Nhìn vào phần lớn đoạn code trên, bạn cũng có thể dễ dàng nhận ra rằng, tuy đều là hành vi nhập, xuất với tính lương, mặc dù nhiên chúng ta lại nên gọi cách tiến hành này cho 2 đối tượng người dùng thuộc kiểu khác biệt là NVVP với NVSX. Còn một điều nữa là tuy gần như là nhân viên nhưng lại bắt buộc dùng 2 vector không giống nhau để lưu trữ 2 đối tượng người tiêu dùng này.

Bạn đang xem: Tính đa hình là gì

Câu hỏi đề ra là liệu có cách làm sao để rất có thể lưu trữ 2 loại nhân viên cấp dưới này trong cùng một vector? Và cách thức nhập, xuất, tính lương có thể tự động biết nó thực hiện hành vi cho đối tượng nào để thực hiện cho đúng không? Câu trả lời là tất cả và nó được triển khai thông qua cách làm ảo. Vậy thì hãy cùng tìm hiểu phương thức ảo là gì?

Phương thức ảo

Phương thức ảo (virtual method) vào C++ là cách thể hiện tại tính nhiều hình trong lập trình hướng đối tượng người dùng của C++, các phương thức ở class cơ sở tất cả tính đa hình cần được định nghĩa là 1 trong những phương thức ảo.

Và nhằm khai báo một cách tiến hành ảo, ta khai báo như thông thường nhưng thêm từ bỏ khóa “virtual” phía trước.

class protected: virtual (<>) ;Ví dụ như trong việc ở trên, các phương thức tính lương, nhập cùng xuất đều có tính đa hình do so với hai đối tượng người tiêu dùng NVSX với NVVP thì sẽ có cách thực hiện phương thức không giống nhau. Vì chưng đó, bản thân sẽ chỉnh sửa 3 cách thức này làm việc class dẫn xuất thành thủ tục ảo như sau:

class NhanVienpublic: virtual void nhap() // code goes here... virtual void xuat() // code goes here... virtual void tinhLuong() // code goes here... ;Chúng ta vẫn có các phương thức ảo, vậy vụ việc hiện tại là làm thế nào để công tác biết thủ tục của đối tượng người dùng nào để tiến hành cho đúng? Thì vào C++, tính đa hình được thể hiện trải qua tham chiếu và nhỏ trỏ. Ví dụ như sau:

Đối cùng với tham chiếu, đối tượng người sử dụng tham chiếu của class cơ sở có thể tham chiếu đến đối tượng thuộc class dẫn xuất. Thời điểm này, lúc gọi cách thức ảo, công tác sẽ hotline đúng phương thức của đối tượng người sử dụng mà biến chuyển tham chiếu tham chiếu tới. Ví dụ:

NhanVienVanPhong nvvp;NhanVien &nv = nv; // phát triển thành nv tham chiếu đến trở thành nvvpnv.nhap(); // cách thức được hotline là sẽ cách tiến hành nhập của class NhanVienVanPhongDo để tham chiếu đến một biến, nên biến kia cần tồn trên trước, vì thế cách tham chiếu khôn cùng ít khi được thực hiện mà nuốm vào đó, bạn ta đang dùng nhỏ trỏ.

Trong bài Kế thừa trong C++, tôi đã có nói nhỏ trỏ của class cơ sở rất có thể trỏ đến đối tượng người tiêu dùng của class dẫn xuất, tính nhiều hình trong C++ chủ yếu đều diễn đạt qua phương pháp này. Cũng giống như như vấn đề tham chiếu, thực hiện qua nhỏ trỏ như sau:

NhanVien *nv = new NhanVienVanPhong; // nhỏ trỏ nv trỏ tới biến động kiểu NhanVienVanPhongnv->nhap(); // cách tiến hành được hotline là sẽ cách tiến hành nhập của class NhanVienVanPhongQuay trở lại với vấn đề ban đầu, giờ đây chúng ta đã rất có thể trả lời nhì câu hỏi. Để lưu trữ 2 đối tượng người sử dụng mà chỉ sử dụng một vector chúng ta sẽ áp dụng con trỏ trỏ đến đối tượng người tiêu dùng thuộc class dẫn xuất. Những phương thức rất có thể được hotline theo đúng đối tượng người dùng thông qua bé trỏ mà vector lưu trữ. Bây giờ chúng ta sẽ sửa lại như sau:

// Thayvector NVVP;vector NVSX;// nghỉ ngơi class CongTy Bằngvector NV;Do trực thuộc tính cố kỉnh đối, những phương thức có tương quan cũng biến đổi theo, ta sẽ sửa lại những phương thức của class CongTy không cần triển khai trên nhì vector không giống nhau, hai đối tượng khác nhau nữa, bọn họ sẽ thực hiện tính nhiều hình, code như sau:

void nhap() cout > n; for (int i = 0; i > k; NhanVien *nv; // Tùy vào người tiêu dùng chọn đối tượng người dùng nào để nhập if (k == 1) nv = new NhanVienVanPhong; else nv = new NhanVienSanXuat; nv->nhap(); // ta sẽ sử dụng hàm nhập của đối tượng mà người tiêu dùng chọn this->NV.push_back(nv); }void xuat() cout NV.size(); i++) cout NV.at(i)->xuat(); // tùy vào đối tượng là gì mà cách tiến hành xuất sẽ tiến hành gọi theo đúng đối tượng đó void tinhLuong() for (int i = 0; i NV.size(); i++) this->NV.at(i)->tinhLuong(); // tùy vào đối tượng người dùng là gì mà cách thức tính lương sẽ được gọi theo đúng đối tượng người dùng đóCơ chế hoạt động của phương thức ảo là dựa trên link động, rất có thể hiểu link động là đối tượng người sử dụng không được xác định cụ thể khi biên dịch nhưng mà chỉ được xác định trong lúc chương trình thực thi.

Nói sang một chút về cách sử dụng tính nhiều hình với hàm. Mang sử bạn muốn tính lương độc lập cho một nhân viên, không ví dụ nhân viên nào nhưng mà sẽ tùy trực thuộc vào nhân viên bạn muốn tính, mình sẽ viết hàm như sau:

// phương pháp 1: tham chiếuvoid tinhLuong(NhanVien &nv) nv.tinhLuong();// phương pháp 2: con trỏ (nên dùng)void tinhLuong(NhanVien *nv) nv->tinhLuong();Rất tiện nghi phải không, nắm vì bài toán phải viết hai hàm để điện thoại tư vấn cho đúng cách làm theo từng đối tượng khác nhau.

Lưu ý: tính nhiều hình chỉ áp dụng được thông qua tham số là tham chiếu hoặc nhỏ trỏ, nếu bạn sử dụng một tham số bình thường, thủ tục của class cơ sở sẽ được gọi vì về thực chất nó là một đối tượng người dùng thuộc kiểu dáng class cơ sở.

void tinhLuong(NhanVien nv) nv.tinhLuong(); // thông số nv trực thuộc class NhanVien cần phương thức tính lương của class NhanVien sẽ tiến hành gọi

Phương thức thuần ảo

Nếu như so với kỹ thêm một chút, các bạn sẽ thấy là class nhân viên thì cách tiến hành tính lương ko có chính vì ta tất yêu tính lương mang đến một nhân viên mà lừng chừng là nhân viên gì. Các class dẫn xuất của nó là một rõ ràng hóa của class cơ sở nhân viên, buộc phải ta có thể tính lương được, ta biết phương pháp tính cho từng nhiều loại nhân viên như thế nào.

Xem thêm: Chất Nào Sau Đây Là Đồng Phân Của Glucozơ Là Chất Nào ? Đồng Phân Của Glucozơ Là Fructozơ

Từ phần nhiều điều trên, ta có khái niệm cách tiến hành thuần ảo. Cách tiến hành thuần ảo (pure virtual method) là cách thức ảo không có phần khái niệm và sẽ phải được override sống class dẫn xuất. Để khai báo cách làm thuần ảo, ta cũng khai báo tương tự như phương thức ảo dẫu vậy thay bởi vì định nghĩa phần thân hàm, ta sẽ mang lại nó bởi 0.

class public: virtual (<>) = 0;;Quay lại với câu hỏi của chúng ta, class nhân viên sẽ không cần có hàm tính lương ví dụ do ta chần chờ tính thế nào khi không xác minh được các loại nhân viên. Với ở class dẫn xuất, chúng ta cần có cách tính lương không giống nhau cho từng loại nhân viên, từ kia suy ra cách tiến hành tính lương vẫn là cách thức thuần ảo. Bọn họ sẽ sửa lại như sau:

class NhanVienpublic: // code goes here... Virtual void tinhLuong() = 0;;Khi mà cách làm tính lương biến hóa thuần ảo, sống class dẫn xuất bắt buộc cần được override lại cách thức này. Chúng ta vẫn thực hiện override bình thường. Vị ở class dẫn xuất tôi đã override rồi đề xuất không đề xuất sửa gì cả.

Lớp trừu tượng

Lớp trừu tượng (abstract class) là 1 trong những class chứa phương thức thuần ảo, thiết yếu tạo một đối tượng người sử dụng thuộc lớp trừu tượng. Điều này hiển nhiên, chính vì nếu class cất một hoặc những phương thức ảo, khi đối tượng người dùng được sản xuất thì cách tiến hành đó sẽ không tồn tại định nghĩa và sẽ gây ra lỗi.

Một lớp trừu tượng bắt buộc có tối thiểu một phương thức thuần ảo cùng nó hoàn toàn có thể cùng có các phương thức và cách làm ảo khác. Những phương thức và phương thức ảo trực thuộc lớp trừu tượng vẫn hoàn toàn có thể được hotline từ class dẫn xuất qua toán tử phạm vi (::) như bình thường.

Lớp trừu tượng tạo cho logic thực tế trở nên hợp lý và phải chăng hơn vào lập trình. Như đã nói ở trên, các bạn không thể tính lương lúc không biết nhân viên đó là nhân viên cấp dưới gì, vị đó, theo logic, ta chẳng thể tạo đối tượng người dùng nhân viên được. Tuyệt nói đúng hơn, ta ko nên có thể chấp nhận được người lập trình hoàn toàn có thể tạo ra đối tượng người dùng nhân viên bằng cách làm mang đến lớp đó vươn lên là lớp thuần ảo.

Vì cách thức nhập, xuất vẫn không bắt buộc override lại trả toàn, do đó mình sẽ lưu lại nguyên, chỉ đổi cách làm tính tiền thành cách tiến hành thuần ảo thôi.

class NhanVienpublic: // Code goes here... Virtual void tinhLuong() = 0;;Lúc này, bất kỳ class nào kế thừa từ class nhân viên đều cần override lại thủ tục tính lương. Và chúng ta cũng thiết yếu tạo được đối tượng nhân viên nữa. Ví dụ:

class NhanVienKiemToan : public NhanVienpublic: void tinhLuong() // override method tinhLuong // nếu không override sẽ nhận thông báo lỗi ;NhanVien nx; // lỗi do không thể tạo đối tượng người sử dụng thuộc abstract classLưu ý là con trỏ class nhân viên vẫn có thể tạo được thông thường (nếu không thì sao áp dụng được nhiều hình :D).

Xem thêm: Giải Bài 18 Trang 75 Sgk Toán 9 Tập 2, Bài 18 Trang 75 Sgk Toán 9 Tập 2

Interface

Phần này reviews thêm cho chúng ta thôi cũng chính vì trong C++ không cung ứng sẵn concept interface, chúng ta nên tò mò concept của các ngôn ngữ tiến bộ khác như C#, Java… tuy nhiên ta vẫn hoàn toàn có thể sử dụng concept của các ngôn ngữ khác mang đến C++.

Interface có thể được hiểu là 1 class trừu tượng trả toàn, nghĩa là phần lớn phương thức của interface gần như là phương thức thuần ảo và bạn sẽ cần bắt buộc override lại tất cả các thủ tục của interface làm việc class dẫn xuất. Ví dụ:

class Animal // Animal là một trong những Interfaceprotected: string sound;public: virtual void move() = 0; virtual void makeNoise() = 0; virtual void eat() = 0;;// Class thừa kế từ Animal đều cần override toàn bộclass Dogpublic: Dog() sound = "Woo - Woo!"; virtual void move() // code goes here... virtual void makeNoise() // code goes here... virtual void eat() // code goes here... ;

Tổng kết

Vậy là trong nội dung bài viết này, bản thân đã reviews cho các bạn về tính nhiều hình vào C++ và các vấn đề tương quan như cách tiến hành ảo, thuần ảo, lớp trừu tượng và interface. Hi vọng là bài viết có ích với mọi người, nhớ là chia sẻ bài viết để mọi người cùng biết nha. Giả dụ có ngẫu nhiên thắc mắc nào các bạn hãy để lại phản hồi phía dưới mình đang phản hồi. Cảm ơn các bạn đã theo dõi bài bác viết!

Source Code

#include using namespace std;#include #include class NhanVienprotected: string hoTen; float luong;public: NhanVien() this->hoTen = ""; this->luong = 0.0; virtual void nhap() cout hoTen); virtual void xuat() cout hoTen soSanPham = 0; this->tienCong1SP = 0; void nhap() NhanVien::nhap(); cout > this->soSanPham; cout > this->tienCong1SP; void xuat() cout soSanPham tienCong1SP luong luong = this->soSanPham * this->tienCong1SP; ;class NhanVienVanPhong : public NhanVienprivate: float luongCoBan; int soNgayLamViec;public: NhanVienVanPhong() : NhanVien() this->luongCoBan = 0.0; void nhap() NhanVien::nhap(); cout > this->luongCoBan; cout > this->soNgayLamViec; void xuat() NhanVien::xuat(); cout luongCoBan soNgayLamViec luong luong = this->soNgayLamViec * this->luongCoBan; ;class CongTyprivate: vector NV;public: void nhap() cout > n; for (int i = 0; i > k; NhanVien *nv; // Tùy vào người dùng chọn đối tượng người tiêu dùng nào để nhập if (k == 1) nv = new NhanVienVanPhong; else nv = new NhanVienSanXuat; nv->nhap(); // ta sẽ sử dụng hàm nhập của đối tượng người tiêu dùng mà người tiêu dùng chọn this->NV.push_back(nv); void xuat() cout NV.size(); i++) cout NV.at(i)->xuat(); // tùy vào đối tượng người tiêu dùng là gì mà cách làm xuất sẽ được gọi theo đúng đối tượng người tiêu dùng đó void tinhLuong() for (int i = 0; i NV.size(); i++) this->NV.at(i)->tinhLuong(); // tùy vào đối tượng là gì mà thủ tục tính lương sẽ được gọi theo đúng đối tượng người sử dụng đó };int main() CongTy cty; cty.nhap(); cty.tinhLuong(); cty.xuat(); return 0;