Menu
CoddyTech

Nạp chồng hàm

Thuộc phần Lập trình hướng đối tượng trong hành trình C++ của Coddy. Bài học 57 trên 104.

Nạp chồng hàm cho phép bạn định nghĩa nhiều hàm (function) cùng tên nhưng có danh sách tham số khác nhau. Trình biên dịch chọn phiên bản phù hợp dựa trên các đối số bạn truyền vào. Đây là một dạng đa hình quan trọng tại thời điểm biên dịch.

Để việc nạp chồng hoạt động, các hàm phải khác nhau về chữ ký: số lượng tham số, kiểu dữ liệu của chúng hoặc cả hai:

class Calculator {
public:
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int add(int a, int b, int c) {
        return a + b + c;
    }
};

Calculator calc;
calc.add(5, 3);        // Gọi add(int, int)
calc.add(2.5, 3.7);    // Gọi add(double, double)
calc.add(1, 2, 3);     // Gọi add(int, int, int)

Trình biên dịch kiểm tra từng lời gọi và khớp lời gọi đó với hàm nạp chồng phù hợp. Việc này diễn ra hoàn toàn trong quá trình biên dịch, nên không phát sinh chi phí khi chạy chương trình.

Quan trọng: Chỉ riêng kiểu trả về không thể phân biệt các hàm nạp chồng. Đoạn code sau sẽ gây ra lỗi biên dịch:

int getValue();
double getValue();  // Lỗi: không thể nạp chồng chỉ dựa vào kiểu giá trị trả về

Việc nạp chồng hàm (function) giúp code của bạn trực quan hơn. Thay vì tạo các tên riêng như addInts, addDoubles và addThreeInts, bạn dùng một tên có ý nghĩa duy nhất và để trình biên dịch xử lý phần còn lại.

challenge icon

Thử thách

Dễ

Hãy xây dựng một lớp định dạng thông điệp để minh họa sức mạnh của nạp chồng hàm. Bạn sẽ tạo lớp Formatter với nhiều phương thức format() xử lý các kiểu đầu vào khác nhau, để trình biên dịch chọn phiên bản phù hợp dựa trên những gì bạn truyền vào.

Bạn sẽ tổ chức code trong hai tệp:

  • Formatter.h: Định nghĩa lớp Formatter với các phương thức format() được nạp chồng để xử lý các trường hợp khác nhau:
    • Một phương thức nhận một std::string và in ra: Message: <text>
    • Một phương thức nhận một std::string và một mức ưu tiên int, rồi in ra: [Priority <priority>] <text>
    • Một phương thức nhận một std::string và một dấu thời gian double, rồi in ra: [<timestamp>s] <text>
    • Một phương thức nhận ba tham số std::string (người gửi, người nhận, thông điệp) và in ra: From <sender> to <receiver>: <message>
    Tất cả phương thức đều có tên format(): trình biên dịch sẽ chọn phương thức phù hợp dựa trên các đối số.
  • main.cpp: Đọc bốn đầu vào (mỗi đầu vào trên một dòng riêng):
    1. Nội dung thông điệp đơn giản
    2. Mức ưu tiên (số nguyên)
    3. Dấu thời gian (số thực)
    4. Tên người gửi

    Tạo một đối tượng Formatter và minh họa cả bốn phương thức được nạp chồng:

    • Gọi format() chỉ với nội dung thông điệp
    • Gọi format() với nội dung thông điệp và mức ưu tiên
    • Gọi format() với nội dung thông điệp và dấu thời gian
    • Gọi format() với người gửi, "Admin" làm người nhận và nội dung thông điệp

Ví dụ, với các đầu vào System ready, 3, 12.5 và Server:

Message: System ready
[Priority 3] System ready
[12.5s] System ready
From Server to Admin: System ready

Hãy chú ý cách bạn gọi cùng một tên phương thức format() bốn lần, nhưng mỗi lần gọi sẽ thực thi một phiên bản khác nhau dựa trên kiểu và số lượng đối số. Đây là tính đa hình tại thời điểm biên dịch: trình biên dịch xác định phương thức nạp chồng nào cần dùng trước khi chương trình chạy.

Tự làm thử

#include <iostream>
#include <string>
#include "Formatter.h"

using namespace std;

int main() {
    // Đọc các giá trị đầu vào
    string message;
    getline(cin, message);
    
    int priority;
    cin >> priority;
    
    double timestamp;
    cin >> timestamp;
    cin.ignore();
    
    string sender;
    getline(cin, sender);
    
    // TODO: Tạo một đối tượng Formatter
    
    // TODO: Gọi format() chỉ với nội dung message
    
    // TODO: Gọi format() với nội dung message và priority
    
    // TODO: Gọi format() với nội dung message và timestamp
    
    // TODO: Gọi format() với sender, "Admin" làm người nhận và nội dung message
    
    return 0;
}
quiz iconTự kiểm tra

Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.

Tất cả bài học trong Lập trình hướng đối tượng

Tự luyện tập: Trình biên dịch C++ online