Lập Trình C++ - Đa Hình (Polymorphsim)
Có thể bạn quan tâm
Đa hình là khái niệm luôn đi kèm với kế thừa. Do tính kế thừa, một lớp có thể sử dụng lại các phương thức của lớp khác. Tuy nhiên, nếu cần thiết, lớp dẫn xuất cũng có thể định nghĩa lại một số phương thức của lớp cơ sở. Đó là sự nạp chồng phương thức trong kế thừa. Nhờ sự nạp chồng phương thức này, ta chỉ cần gọi tên phương thức bị nạp chồng từ đối tượng mà không cần quan tâm đó là đối tượng của lớp nào. Chương trình sẽ tự động kiểm tra xem đối tượng là thuộc kiểu lớp cơ sở hay thuộc lớp dẫn xuất, sau đó sẽ gọi phương thức tương ứng với lớp đó. Đó là tính đa hình.
Đặt vấn đề 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 Bus kế thừa từ lớp Car, cả hai lớp này đều định nghĩa phương thức show()
class Car{ public: void show(); }; class Bus: public Car{ public: void show(); };khi đó, nếu ta khai báo một con trỏ lớp Bus, nhưng lại trỏ vào địa chỉ của một đối tượng lớp Car:
Bus myBus; Car *ptrCar = &myBus; // đúng nhưng khi gọi: ptrCar->show();thì chương trình sẽ gọi đến phương thức show() của lớp Car (là kiểu của con trỏ ptrCar), mà không gọi tới phương thức show() của lớp Bus (là kiểu của đối tượng myBus mà con trỏ ptrCar đang trỏ tới). Để giải quyết vấn đề này, C++ đưa ra một khái niệm là phương thức trừu tượng. Bằng cách sử dụng phương thức trừu tượng. Khi gọi một phương thức từ một con trỏ đối tượng, trình biên dịch sẽ xác định kiểu của đối tượng mà con trỏ đang trỏ đến, sau đó nó sẽ gọi phương thức tương ứng với đối tượng mà con trỏ đang trỏ tới.
Khai báo phương thức trừu tượng Phương thức trừu tượng (còn gọi là phương thức ảo, hàm ảo) được khai báo với từ khoá virtual:
- Nếu khai báo trong phạm vi lớp: virtual <Kiểu trả về> <Tên phương thức>([<Các tham số>]);
-
Nếu định nghĩa ngoài phạm vi lớp:
virtual <Kiểu trả về> <Tên lớp>::<Tên phương thức>([<Các tham số>]){…}
Ví dụ:
class Car{ public: virtual void show(); };là khai báo phương thức trừu tượng show() của lớp Car: phương thức không có tham số và không cần giá trị trả về (void). Lưu ý:
- Từ khoá virtual có thể đặt trước hay sau kiểu trả về của phương thức.
- Với cùng một phương thức được khai báo ở lớp cơ sở lẫn lớp dẫn xuất, chỉ cần dùng từ khoá virtual ở một trong hai lần định nghĩa phương thức đó là đủ: hoặc ở lớp cơ sở, hoặc ở lớp dẫn xuất.
- Trong trường hợp cây kế thừa có nhiều mức, cũng chỉ cần khai báo phương thức là trừu tượng (virtual) ở một mức bất kì. Khi đó, tất cả các phương thức trùng tên với phương thức đó ở tất cả các mức đều được coi là trừu tượng.
- Đôi khi không cần thiết phải định nghĩa chồng (trong lớp dẫn xuất) một phương thức đã được khai báo trừu tượng trong lớp cơ sở.
Sử dụng phương thức trừu tượng – đa hình Một khi phương thức được khai báo là trừu tượng thì khi một con trỏ gọi đến phương thức đó, chương trình sẽ thực hiện phương thức tương ứng với đối tượng mà con trỏ đang trỏ tới, thay vì thực hiện phương thức của lớp cùng kiểu với con trỏ. Đây được gọi là hiện tượng đa hình (tương ứng bội) trong C++. Chương trình sau ví dụ về việc sử dụng phương thức trừu tượng: lớp Bus kế thừa từ lớp Car, hai lớp này cùng định nghĩa phương thức trừu tượng show().
- Khi ta dùng một con trỏ có kiểu lớp Car trỏ vào địa chỉ của một đối tượng kiểu Car, nó sẽ gọi phương thức show() của lớp Car.
- Khi ta dùng cũng con trỏ đó, trỏ vào địa chỉ của một đối tượng kiểu Bus, nó sẽ gọi phương thức show() của lớp Bus.
Xem ví dụ sau:
#include<iostream> #include<string> using namespace std; /* Định nghĩa lớp */ class Car { private: int speed; // Tốc độ string mark; // Nhãn hiệu float price; // Giá xe // Khởi tạo với các giá trị ngầm định cho các tham số public: Car(); Car(int speed, string mark, float price); virtual void show(); // Giới thiệu xe, trừu tượng int getSpeed() { return speed; }; string getMark() { return mark; }; float getPrice() { return price; }; }; /* Khai báo phương thức bên ngoài lớp */ Car::Car() { this->speed = 0; this->mark = ""; this->price = 0; } Car::Car(int speed, string mark, float price) { this->speed = speed; this->mark = mark; this->price = price; } void Car::show() { // Phương thức hiển thị xe cout << "This is a " << mark << " having a speed of " << speed << "km/h and its price is $" << price << endl; } /* Định nghĩa lớp Bus kế thừa từ lớp Car */ class Bus : public Car { int label; // Số hiệu tuyến xe public: // Khởi tạo đủ tham số Bus(int speed = 0, string mark = "", float price = 0, int lable = 0); void setLabel(int); // Gán số hiệu tuyến xe int getLabel(); // Đọc số hiệu tuyến xe void show(); }; // Cài đặt lớp Bus Bus::Bus(int speed, string mark, float price, int label) :Car(speed, mark, price) { this->label = label; } // Định nghĩa nạp chồng phương thức void Bus::show() { // Giới thiệu xe bus cout << "This is a bus of type " << getMark() << ", on the line " << label << ", having a speed of " << getSpeed() << "km / h and its price is $" << getPrice() << endl; return; } int main() { Car *ptrCar, myCar(100, "Ford", 3000); Bus myBus(150, "Mercedes", 5000, 27);// Biến đối tượng của lớp Bus ptrCar = &myCar; // Trỏ đến đối tượng lớp Car ptrCar->show(); // Phương thức của lớp Car ptrCar = &myBus; // Trỏ đến đối tượng lớp Bus ptrCar->show(); // Phương thức của lớp Bus return; // Hàm của lớp Bus system("pause"); return 0; }Chương trình trên hiển thị kết quả thông báo như sau:
This is a Ford having a speed of 100km/h and its price is $3000 This is a bus of type Mercedes, on the line 27, having a speed of 150km / h and its price is $5000Từ khóa » đa Xạ Trong C++
-
Đa Hình Trong C++ | TopDev
-
Tính Đa Hình Trong Lập Trình Hướng Đối Tượng - CodeLearn
-
Tính Đa Hình Trong Lập Trình Hướng Đối Tượng
-
Tính đa Hình Trong C++ - Học Lập Trình C++ Online - VietTuts
-
Đa Hình Trong C++ - Techacademy
-
Polymorphism In C++ - Viblo
-
Kế Thừa & đa Hình Trong Lập Trình Hướng đối Tượng - CppDeveloper
-
2.8. Tính đa Hình - Lập Trình Tân Binh
-
Tính đa Hình Trong OOP Và Những Loại đa Hình Bạn Cần Biết
-
Đa Hình Trong Lập Trình Hướng đối Tượng | How Kteam
-
C++ Hỗ Trợ đa Kế Thừa Trong Lập Trình Hướng đối Tượng - Góc Học IT
-
Đa Hình Trong C++ - TEK4
-
Tính đa Hình Trong Lập Trình Hướng đối Tượng - .vn
-
Tính đa Hình, Phương Thức ảo, Lớp Trừu Tượng Trong C++
-
Chi Tiết Bài Học Đa Kế Thừa Và Kế Thừa Nhiều Tầng - Vimentor
-
Top 13 đa Hình Là Gì
-
Tính đa Hình (Polymorphism) Trong C# Là Gì? Khái Niệm ... - Thủ Thuật