Đa hình C ++ với ví dụ

Mục lục:

Anonim

Đa hình trong C ++ là gì?

Trong C ++, tính đa hình khiến một hàm thành viên hoạt động khác nhau dựa trên đối tượng gọi / gọi nó. Đa hình là một từ Hy Lạp có nghĩa là có nhiều hình thức. Nó xảy ra khi bạn có một hệ thống phân cấp các lớp liên quan thông qua kế thừa.

Ví dụ, giả sử chúng ta có hàm makeSound (). Khi mèo gọi chức năng này, nó sẽ tạo ra âm thanh meo meo. Khi một con bò gọi cùng một chức năng, nó sẽ cung cấp âm thanh kêu rên.

Mặc dù chúng ta có một chức năng, nhưng nó hoạt động khác nhau trong các trường hợp khác nhau. Hàm có nhiều dạng; do đó, chúng tôi đã đạt được tính đa hình.

Trong hướng dẫn C ++ này, bạn sẽ học:

  • Đa hình là gì?
  • Các loại đa hình
  • Biên dịch đa hình thời gian
  • Quá tải chức năng
  • Người vận hành quá tải
  • Đa hình thời gian chạy
  • Ghi đè chức năng
  • Hàm ảo C ++
  • Tính đa hình thời gian biên dịch Vs. Đa hình thời gian chạy

Các loại đa hình

C ++ hỗ trợ hai kiểu đa hình:

  • Tính đa hình thời gian biên dịch và
  • Tính đa hình thời gian chạy.

Biên dịch đa hình thời gian

Bạn gọi các hàm được nạp chồng bằng cách so khớp số lượng và kiểu đối số. Thông tin hiện diện trong thời gian biên dịch. Điều này có nghĩa là trình biên dịch C ++ sẽ chọn đúng chức năng tại thời điểm biên dịch.

Tính đa hình thời gian biên dịch đạt được thông qua quá trình nạp chồng hàm và nạp chồng toán tử.

Quá tải chức năng

Quá tải hàm xảy ra khi chúng ta có nhiều hàm có tên giống nhau nhưng đối số khác nhau. Các đối số có thể khác nhau về số lượng hoặc kiểu.

Ví dụ 1:

#include using namespace std;void test(int i) {cout << " The int is " << i << endl;}void test(double f) {cout << " The float is " << f << endl;}void test(char const *ch) {cout << " The char* is " << ch << endl;}int main() {test(5);test(5.5);test("five");return 0;}

Đầu ra:

Đây là ảnh chụp màn hình của mã:

Giải thích mã:

  1. Bao gồm tệp tiêu đề iostream vào mã của chúng tôi. Chúng tôi sẽ có thể sử dụng các chức năng của nó.
  2. Bao gồm không gian tên std trong mã của chúng tôi. Chúng ta sẽ có thể sử dụng các lớp của nó mà không cần gọi nó.
  3. Tạo một hàm có tên test nhận tham số nguyên i. Dấu {đánh dấu phần bắt đầu của phần nội dung kiểm tra chức năng.
  4. Câu lệnh sẽ được thực hiện nếu kiểm tra hàm trên được gọi / gọi.
  5. Kết thúc cơ thể của bài kiểm tra chức năng trên.
  6. Tạo một hàm có tên là test có tham số float là f. Dấu {đánh dấu phần bắt đầu của phần nội dung kiểm tra chức năng.
  7. Câu lệnh sẽ được thực hiện nếu kiểm tra hàm trên được gọi / gọi.
  8. Kết thúc phần thân của bài kiểm tra chức năng trên.
  9. Tạo một hàm có tên test nhận tham số ký tự ch. Dấu {đánh dấu phần bắt đầu của phần nội dung kiểm tra chức năng.
  10. Câu lệnh sẽ được thực hiện nếu kiểm tra hàm trên được gọi / gọi.
  11. Kết thúc phần thân của bài kiểm tra chức năng trên.
  12. Gọi hàm main (). Dấu {đánh dấu phần đầu của phần thân của hàm.
  13. Gọi kiểm tra hàm và chuyển 5 cho nó làm giá trị của đối số. Điều này gọi hàm kiểm tra chấp nhận một đối số nguyên, tức là, hàm kiểm tra đầu tiên.
  14. Gọi kiểm tra hàm và chuyển 5.5 cho nó làm giá trị của đối số. Điều này sẽ gọi hàm kiểm tra chấp nhận một đối số float, tức là, hàm kiểm tra thứ hai.
  15. Gọi kiểm tra hàm và chuyển năm cho nó làm giá trị của đối số. Điều này sẽ gọi hàm kiểm tra chấp nhận một đối số ký tự, tức là hàm kiểm tra thứ ba.
  16. Chương trình phải trả về một giá trị nếu nó chạy thành công.
  17. Phần cuối của phần thân của hàm main ().

Chúng ta có ba hàm có cùng tên nhưng khác loại đối số. Chúng tôi đã đạt được tính đa hình.

Người vận hành quá tải

Trong Nạp chồng toán tử, chúng tôi xác định nghĩa mới cho toán tử C ++. Nó cũng thay đổi cách thức hoạt động của nhà điều hành. Ví dụ, chúng ta có thể định nghĩa toán tử + để nối hai chuỗi. Chúng tôi biết nó như là toán tử cộng để thêm các giá trị số. Sau định nghĩa của chúng tôi, khi được đặt giữa các số nguyên, nó sẽ thêm chúng vào. Khi được đặt giữa các chuỗi, nó sẽ nối chúng.

Ví dụ 2:

#includeusing namespace std;class ComplexNum {private:int real, over;public:ComplexNum(int rl = 0, int ov = 0) {real = rl;over = ov;}ComplexNum operator + (ComplexNum const &obj) {ComplexNum result;result.real = real + obj.real;result.over = over + obj.over;return result;}void print() {cout << real << " + i" << over << endl;}};int main(){ComplexNum c1(10, 2), c2(3, 7);ComplexNum c3 = c1+c2;c3.print();}

Đầu ra:

Đây là ảnh chụp màn hình của mã:

Giải thích mã:

  1. Đưa tệp tiêu đề iostream vào chương trình của chúng tôi để sử dụng các chức năng của nó.
  2. Bao gồm không gian tên std vào chương trình của chúng tôi để sử dụng các lớp của nó mà không cần gọi nó.
  3. Tạo một lớp có tên là ComplexNum. Dấu {đánh dấu phần đầu của phần thân lớp.
  4. Sử dụng công cụ sửa đổi quyền truy cập riêng tư để đánh dấu các biến là riêng tư, nghĩa là chúng chỉ có thể được truy cập từ bên trong lớp.
  5. Xác định hai biến số nguyên, thực và hơn.
  6. Sử dụng công cụ sửa đổi truy cập công khai để đánh dấu phương thức khởi tạo là công khai, có nghĩa là nó sẽ có thể truy cập được ngay cả từ bên ngoài lớp.
  7. Tạo phương thức khởi tạo lớp và khởi tạo các biến.
  8. Khởi tạo giá trị của biến real.
  9. Khởi tạo giá trị của biến trên.
  10. Phần cuối của phần thân hàm tạo.
  11. Chúng ta cần ghi đè ý nghĩa của toán tử +.
  12. Tạo kết quả kiểu dữ liệu kiểu ComplexNum.
  13. Sử dụng toán tử + với các số phức. Dòng này sẽ thêm phần thực của một số vào phần thực của một số khác.
  14. Sử dụng toán tử + với các số phức. Dòng này sẽ thêm phần ảo của một số vào phần ảo của một số khác.
  15. Chương trình sẽ trả về giá trị của kết quả biến khi thực hiện thành công.
  16. Kết thúc định nghĩa về nghĩa mới của toán tử +, tức là nạp chồng.
  17. Gọi phương thức print ().
  18. In số phức mới sau khi cộng trên bảng điều khiển.
  19. Cuối phần nội dung của hàm print ().
  20. Cuối phần thân của lớp ComplexNum.
  21. Gọi hàm main ().
  22. Chuyển các giá trị của cả phần thực và phần phức tạp được thêm vào. Phần đầu tiên của c1 sẽ được thêm vào phần đầu tiên của c2, tức là 10 + 3. Phần thứ hai của c1 sẽ được thêm vào phần thứ hai của c, tức là, 2 + 7.
  23. Thực hiện một hoạt động bằng cách sử dụng toán tử + được nạp chồng và lưu trữ kết quả trong biến c3.
  24. In giá trị của biến c3 trên bàn điều khiển.
  25. Cuối phần thân của hàm main ().

Đa hình thời gian chạy

Điều này xảy ra khi phương thức của một đối tượng được gọi / gọi trong thời gian chạy chứ không phải trong thời gian biên dịch. Đa hình thời gian chạy đạt được thông qua ghi đè chức năng. Hàm được gọi / được gọi được thiết lập trong thời gian chạy.

Ghi đè chức năng

Ghi đè hàm xảy ra khi một hàm của lớp cơ sở được đưa ra một định nghĩa mới trong một lớp dẫn xuất. Tại thời điểm đó, chúng ta có thể nói hàm cơ sở đã bị ghi đè.

Ví dụ:

#include using namespace std;class Mammal {public:void eat() {cout << "Mammals eat… ";}};class Cow: public Mammal {public:void eat() {cout << "Cows eat grass… ";}};int main(void) {Cow c = Cow();c.eat();return 0;}

Đầu ra:

Đây là ảnh chụp màn hình của mã:

Giải thích mã:

  1. Nhập tệp tiêu đề iostream vào chương trình của chúng tôi để sử dụng các chức năng của nó.
  2. Bao gồm không gian tên std vào chương trình của chúng tôi để sử dụng các lớp của nó mà không cần gọi nó.
  3. Tạo một lớp có tên là Mammal. Dấu {đánh dấu phần đầu của phần thân lớp.
  4. Sử dụng công cụ sửa đổi quyền truy cập công khai để đặt chức năng chúng tôi sắp tạo là có thể truy cập công khai. Nó sẽ có thể truy cập được từ bên ngoài lớp này.
  5. Tạo một hàm công khai có tên là eat. Dấu {đánh dấu phần đầu của thân hàm.
  6. In câu lệnh được thêm vào hàm cout khi hàm eat () được gọi.
  7. Phần cuối của phần thân của hàm eat ().
  8. Cuối cơ thể của lớp Động vật có vú.
  9. Tạo một lớp có tên Bò kế thừa lớp Động vật có vú. Bò là lớp dẫn xuất, trong khi Động vật có vú là lớp cơ sở. Dấu {đánh dấu sự bắt đầu của lớp này.
  10. Sử dụng công cụ sửa đổi quyền truy cập công khai để đánh dấu chức năng chúng tôi sắp tạo là có thể truy cập công khai. Nó sẽ có thể truy cập được từ bên ngoài lớp này.
  11. Ghi đè hàm eat () đã được định nghĩa trong lớp cơ sở. Dấu {đánh dấu phần đầu của thân hàm.
  12. Câu lệnh sẽ in trên bảng điều khiển khi hàm này được gọi.
  13. Cuối phần thân của hàm eat ().
  14. Cuối cơ thể của lớp Bò.
  15. Gọi hàm main (). Dấu {đánh dấu phần bắt đầu của phần thân của hàm này.
  16. Tạo một thể hiện của lớp Cow và đặt tên cho nó c.
  17. Gọi hàm eat () được định nghĩa trong lớp Cow.
  18. Chương trình phải trả về một giá trị sau khi hoàn thành thành công.
  19. Kết thúc hàm main ().

Hàm ảo C ++

Một hàm ảo là một cách khác để triển khai tính đa hình thời gian chạy trong C ++. Nó là một hàm đặc biệt được định nghĩa trong một lớp cơ sở và được định nghĩa lại trong lớp dẫn xuất. Để khai báo một hàm ảo, bạn nên sử dụng từ khóa virtual. Từ khóa phải đứng trước phần khai báo của hàm trong lớp cơ sở.

Nếu một lớp hàm ảo được kế thừa, lớp ảo sẽ xác định lại hàm ảo cho phù hợp với nhu cầu của nó. Ví dụ:

#include using namespace std;class ClassA {public:virtual void show() {cout << "The show() function in base class invoked… " << endl;}};class ClassB :public ClassA {public:void show() {cout << "The show() function in derived class invoked… ";}};int main() {ClassA* a;ClassB b;a = &b;a->show();}

Đầu ra:

Đây là ảnh chụp màn hình của mã:

Giải thích mã:

  1. Bao gồm tệp tiêu đề iostream trong mã để sử dụng các chức năng của nó.
  2. Bao gồm không gian tên std trong mã của chúng tôi để sử dụng các lớp của nó mà không cần gọi nó.
  3. Tạo một lớp có tên ClassA.
  4. Sử dụng công cụ sửa đổi quyền truy cập công khai để đánh dấu một thành viên trong lớp là có thể truy cập công khai.
  5. Tạo một hàm ảo có tên show (). Nó sẽ là một chức năng công cộng.
  6. Văn bản sẽ in khi hiển thị () được gọi ra. Endl là một từ khóa C ++, có nghĩa là dòng kết thúc. Nó di chuyển con trỏ chuột đến dòng tiếp theo.
  7. Cuối phần thân của hàm ảo show ().
  8. Cuối phần thân của lớp ClassA.
  9. Tạo một lớp mới có tên ClassB kế thừa lớp ClassA. ClassA trở thành lớp cơ sở trong khi ClassB trở thành lớp dẫn xuất.
  10. Sử dụng công cụ sửa đổi quyền truy cập công khai để đánh dấu một thành viên trong lớp là có thể truy cập công khai.
  11. Định nghĩa lại hàm ảo show () dẫn xuất trong lớp cơ sở.
  12. Văn bản để in trên bảng điều khiển khi hàm show () được định nghĩa trong lớp dẫn xuất được gọi.
  13. Kết thúc phần nội dung của hàm show ().
  14. Phần cuối của lớp dẫn xuất, ClassB.
  15. Gọi hàm main (). Logic của chương trình nên được thêm vào bên trong phần thân của nó.
  16. Tạo một biến con trỏ có tên là a. Nó trỏ đến lớp có tên ClassA.
  17. Tạo một thể hiện của lớp có tên ClassB. Thể hiện được đặt tên b.
  18. Gán các giá trị lưu trong địa chỉ b trong biến a.
  19. Gọi hàm show () được định nghĩa trong lớp dẫn xuất. Ràng buộc muộn đã được thực hiện.
  20. Cuối phần thân của hàm main ().

Tính đa hình thời gian biên dịch Vs. Đa hình thời gian chạy

Dưới đây là sự khác biệt chính giữa hai loại:

Tính đa hình thời gian biên dịch Đa hình thời gian chạy
Nó còn được gọi là liên kết sớm hoặc đa hình tĩnh Nó còn được gọi là liên kết trễ / động hoặc đa hình động
Phương thức được gọi / gọi trong thời gian biên dịch Phương thức được gọi / gọi trong thời gian chạy
Thực hiện thông qua nạp chồng hàm và nạp chồng toán tử Thực hiện thông qua ghi đè phương thức và các hàm ảo
Ví dụ, nạp chồng phương thức. Nhiều phương thức có thể có tên tương tự nhưng số lượng hoặc kiểu đối số khác nhau Ví dụ, ghi đè phương thức. Nhiều phương pháp có thể có tên giống nhau và cùng một nguyên mẫu.
Thực thi nhanh hơn vì việc khám phá các phương thức được thực hiện trong thời gian biên dịch Thực thi chậm hơn vì trình phát hiện phương thức được thực hiện trong thời gian chạy.
Ít linh hoạt hơn cho việc giải quyết vấn đề được cung cấp vì mọi thứ đều được biết trong thời gian biên dịch. Nhiều tính linh hoạt được cung cấp để giải quyết các vấn đề phức tạp vì các phương pháp được phát hiện trong thời gian chạy.

Tóm lược:

  • Đa hình có nghĩa là có nhiều hình thức.
  • Nó xảy ra khi có một hệ thống phân cấp của các lớp liên quan thông qua kế thừa.
  • Với tính đa hình, một hàm có thể hoạt động khác nhau dựa trên đối tượng gọi / gọi nó.
  • Trong đa hình thời gian biên dịch, hàm được gọi được thiết lập trong thời gian biên dịch.
  • Trong đa hình thời gian chạy, hàm được gọi được thiết lập trong thời gian chạy.
  • Tính đa hình thời gian biên dịch được xác định thông qua quá tải hàm và nạp chồng toán tử.
  • Trong nạp chồng hàm, có nhiều hàm có tên giống nhau nhưng đối số khác nhau.
  • Các tham số có thể khác nhau về số lượng hoặc kiểu.
  • Trong nạp chồng toán tử, một ý nghĩa mới được xác định cho các toán tử C ++.
  • Đa hình thời gian chạy đạt được thông qua ghi đè chức năng.
  • Trong ghi đè hàm, một lớp dẫn xuất đưa ra một định nghĩa mới cho một hàm được định nghĩa trong lớp cơ sở.