C++: Bài 2. Thừa kế


Đăng ký nhận thông báo về những video mới nhất

Một trong những khái nhiệm quan trọng nhất của lập trình hướng đối tượng là thừa kế. Thừa kế cho phép ta định nghĩa một lớp với các thành phần của lớp khác, điều này giúp ta dễ tạo và bảo trì ứng dụng hơn. Thừa kế cũng giúp cung cấp một khả năng tái sử dụng code cũng như thời gian thực thi nhanh hơn.

Khi tạo một lớp thì thay vì phải viết toàn bộ các thành phần dữ liệu cũng như các phương thức từ đầu, ta có thể thừa kế những thành phần đã có ở lớp khác từ trước. Lớp đã có này gọi là lớp cơ sở (lớp cha), và lớp mới gọi là lớp dẫn xuất (lớp con).

Ý tưởng của việc thừa kế đó là dựa trên mối quan hệ. Ví dụ như lớp Mèo thuộc về lớp Động Vật chẳng hạn, thì lớp Mèo thừa kế những thành phần của lớp Động Vật thay vì phải viết lại từ đầu.

Lớp cha và lớp con

Một lớp có thể được dẫn xuất từ ​​nhiều lớp, có nghĩa là nó có thể kế thừa dữ liệu và hàm từ nhiều lớp cơ sở. Để định nghĩa một lớp dẫn xuất, ta sử dụng danh sách dẫn xuất lớp để chỉ định (các) lớp cơ sở. Một danh sách dẫn xuất lớp đặt tên cho một hoặc nhiều lớp cơ sở và có dạng:

class lớp_dẫn_xuất: mức_truy_cập lớp_cơ_sở

Trong đó mức_truy_cập là public, protected hoặc private, và lớp_cơ_sở là tên của một lớp đã được định nghĩa trước đó. Nếu thông số truy cập không được sử dụng, thì nó là riêng tư theo mặc định.

Ví dụ sau thể hiện lớp cơ sở là Shape và lớp dẫn xuất là Rectangle:

#include<iostream>
using namespace std;

// Lp cơ sclass Shape {
  public:
    void setWidth(int w) {
      width = w;
    }
    void setHeight(int h) {
      height = h;
    }

  protected:
    int width;
    int height;
};

// Lp dn xut
class Rectangle: public Shape {
  public:
    int getArea() {
      return (width * height);
    }
};

main() {
  Rectangle Rect;

  Rect.setWidth(5);
  Rect.setHeight(7);

  // In ra din tích ca đi tượng Rect:
  cout << "Dien tich la: " << Rect.getArea() << endl;

  return 0;
}

Kết quả:

Dien tich la: 35

Kiểm soát truy cập và kế thừa

Một lớp dẫn xuất có thể truy cập tất cả các thành phần không riêng tư (private) của lớp cơ sở của nó. Do đó, các thành phần lớp cơ sở không thể truy cập vào các hàm thành phần của các lớp dẫn xuất được khai báo là private trong lớp cơ sở.

Dưới đây là tóm tắt các kiểu và khả năng truy cập:

Kiểu truy cập public protected private
Cùng một lớp Được Được Được
Các lớp dẫn xuất Được Được Không
Các lớp bên ngoài Được Không Không

Một lớp dẫn xuất kế thừa tất cả các phương thức của lớp cơ sở với các ngoại lệ sau:

  • Các hàm tạo, hàm hủy và các hàm tạo sao chép của lớp cơ sở.
  • Các toán tử bị quá tải của lớp cơ sở.
  • Các hàm bạn của lớp cơ sở.

Loại thừa kế

Khi dẫn xuất một lớp từ một lớp cơ sở, lớp cơ sở có thể được kế thừa thông qua kế thừa public, protected hoặc private. Kiểu kế thừa được chỉ định bởi mức độ truy cập như đã giải thích ở trên.

Ta hầu như không sử dụng kế thừa protected hoặc private, nhưng kế thừa public thường được sử dụng. Trong khi sử dụng loại kế thừa khác, các quy tắc sau được áp dụng:

  • Thừa kế public: Khi dẫn xuất một lớp từ một lớp cơ sở public, các thành viên public của lớp cơ sở trở thành thành viên public của lớp dẫn xuất và các thành viên protected của lớp cơ sở trở thành thành viên protected của lớp dẫn xuất. Các thành viên private của lớp cơ sở không bao giờ có thể truy cập trực tiếp từ lớp dẫn xuất, nhưng có thể được truy cập thông qua các lệnh gọi đến các thành viên public và protected của lớp cơ sở.
  • Kế thừa protected: Khi xuất phát từ lớp cơ sở protected, các thành viên public và protected của lớp cơ sở trở thành thành viên protected của lớp dẫn xuất.
  • Kế thừa private: Khi dẫn xuất từ ​​lớp cơ sở private, các thành viên public và protected của lớp cơ sở trở thành thành viên private của lớp dẫn xuất.

Đa thừa kế

Một lớp C++ có thể kế thừa các thành viên từ nhiều hơn một lớp và đây là cú pháp mở rộng:

class lớp_dẫn_xuất: access baseA, access baseB….

Trong đó access là một trong những quyền public, protected hoặc private và sẽ được cấp cho mọi lớp cơ sở và chúng sẽ được phân tách bằng dấu phẩy như hình trên. Ta xem ví dụ sau:

#include<iostream>
using namespace std;

// lp cơ s Shape
class Shape {
  public:
    void setWidth(int w) {
      width = w;
    }
    void setHeight(int h) {
      height = h;
    }

  protected:
    int width;
    int height;
};

// lp cơ s PaintCost
class PaintCost {
  public:
    int getCost(int area) {
      return area * 70;
    }
};

// lp dn xut
class Rectangle: public Shape, public PaintCost {
  public:
    int getArea() {
      return (width * height);
    }
};

main(void) {
  Rectangle Rect;
  int area;

  Rect.setWidth(5);
  Rect.setHeight(7);

  area = Rect.getArea();

  // in ra din tích ca đi tượng:
  cout << "Total area: " << Rect.getArea() << endl;

  // in ra giá ca đi tượng:
  cout << "Total paint cost: $" << Rect.getCost(area) << endl;

  return 0;
}

Kết quả:

Total area: 35
Total paint cost: $2450

Nếu bạn có điều thắc mắc, bạn hãy comment cho V1Study để được giải đáp.
Bài viết này được chia sẻ bởi LongDT. Nếu bạn muốn chia sẻ bài viết, bạn hãy Đăng ký làm thành viên!
« Prev
Next »
Copied !!!