Tại sao dùng virtual trong c

Đa hình là một trong bốn tính chất đặc trưng của lập trình hướng đối tượng bên cạnh 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 mà các đối tượng thuộc các class khác nhau có thể biểu diễn cùng một thông thiệp theo các cách khác nhau. Hơi nặng về lý thuyết một chút nhưng xem ví dụ sau bạn sẽ rõ ngay!

  1001 Tips: Con trỏ và hàm [Pointer & Function] trong C++

  Bảng băm trong C++

Ví dụ hai con vật là con chó và con mèo, hai con vật này đều có thể phát ra tiếng nhưng con mèo sẽ kêu “meo meo” còn con chó lại sủa “gâu gâu”. Hành động phát ra tiếng này tuy là một hành động nhưng khi được 2 đối tượng khác nhau là chó và mèo thực hiện thì lại khác nhau.

Trước khi đi vào chi tiết, hãy chắc chắn rằng bạn đã nắm được các kiến thức sau:

  • Con trỏ và cấp phát động trong C++
  • Cơ bản về Class trong C++
  • Kế thừa trong C++
  • Vector trong C++

Các loại đa hình

Có hai loại đa hình, một là Compile time Polymorphism và Runtime Polymorphism. Compile time Polymorphism nghĩa là cách mà đối tượng thực hiện thông điệp được xác định ngay lúc biên dịch chương trình. Ví dụ cơ bản của Compile time Polymorphism là Overriding và Overloading.

Khi bạn overloading, các hàm đó sẽ có cùng tên nhưng khác tham số, đó chính là đa hình, cùng là một hàm nhưng với các đối tượng là các tham số khác nhau thì hành động thực hiện cũng sẽ khác nhau. Tương tự với overriding, phương thức ở class cơ sở bị override ở class dẫn xuất, điều đó làm cho tuy cùng một phương thức nhưng đối tượng thuộc class cơ sở sẽ thực hiện khác đối tượng thuộc class dẫn xuất.

Đối với Runtime Polymorphism, cách mà đối tượng thực hiện thông điệp không được xác định lúc biên dịch mà nó chỉ được xác định khi chương trình được thực thi. Sử dụng lại ví dụ ban đầu, vẫn là hành động phát ra tiếng của chó và mèo, tuy nhiên, bạn sẽ không thể biết thực hiện như thế nào cho đến khi biết đối tượng là con chó hay mèo để thực hiện kêu “meo meo” hay là sủa “gâu gâu”.

Compile time Polymorphism thì chắc các bạn cũng đã quá quen thuộc rồi, trong bài viết này, mình sẽ chỉ giới thiệu Runtime Polymorphism thôi.

Lợi ích của đa hình

Như định nghĩa của đa hình, đa hình thực hiện cùng một thông điệp theo các cách khác nhau, do đó, code của chúng ta sẽ không bị lặp.

Ví dụ mình có bài toán công ty quản lý hai loại nhân viên là nhân viên văn phòng [NVVP] và nhân viên sản xuất [NVSX], mình sẽ cho người dùng nhập nhân nhiên và tính lương sau đó xuất ra. Mình sẽ có sơ đồ class như sau:

Sơ đồ Class

Dựa trên sơ đồ đã xây dựng, mình sẽ code các class như sau:

class NhanVien { protected: string hoTen; float luong; public: NhanVien[] { this->hoTen = ""; this->luong = 0.0; } void nhap[] { cout hoTen]; } void xuat[] { cout tienCong1SP = 0; } void nhap[] { NhanVien::nhap[]; cout > this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout luongCoBan; cout > this->soNgayLamViec; } void xuat[] { NhanVien::xuat[]; cout m; for [int i = 0; i < m; i++] { NhanVienSanXuat nv; nv.nhap[]; this->NVSX.push_back[nv]; } } void xuat[] { cout n; for [int i = 0; i < n; i++] { cout > k; NhanVien *nv; // Tùy vào người dùng chọn đối tượ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 dùng chọn this->NV.push_back[nv]; } } void xuat[] { cout NV.at[i]->tinhLuong[]; // tùy vào đối tượng là gì mà phương thức tính lương sẽ được gọi theo đúng đối tượng đó }

Cơ chế hoạt động của phương thức ảo là dựa trên liên kết động, có thể hiểu liên kết động là đối tượng không được xác định cụ thể khi biên dịch mà chỉ được xác định trong lúc chương trình thực thi.

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

class NhanVienSanXuat : public NhanVien { private: 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 this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout this->soSanPham; cout > this->tienCong1SP; } void xuat[] { cout

Chủ Đề