← Danh sách bài học
🧩

Hàm

Hàm gói một khối logic có tên, tái sử dụng được. Giúp chia nhỏ chương trình, dễ đọc, dễ test.

1. Khai báo và định nghĩa

Cú pháp: kiểu_trả_về tên(tham_số) { thân; return giá_trị; }

int cong(int a, int b) { return a + b; }
int main() { cout << cong(3, 5); }

2. Truyền tham số: value, reference, const reference

Value: sao chép — an toàn nhưng chậm với object lớn. Reference (&): làm việc trực tiếp trên biến gốc, có thể sửa. Const reference (const &): không sao chép, không sửa — dùng cho object lớn read-only.

void tang(int& x) { x++; }        // sửa được
double tong(const vector<int>& v);  // không copy vector

3. Đệ quy

Hàm gọi lại chính nó. Cần base case (điểm dừng) để tránh tràn stack. Ứng dụng: giai thừa, Fibonacci, duyệt cây, chia để trị.

4. Overloading và giá trị mặc định

Nhiều hàm cùng tên, khác chữ ký. Giá trị mặc định: void log(string msg, int level = 1);

💻 Code mẫu thực chiến

Chuyển tiền tệ

Hàm tổng quát convert(số_tiền, tỷ_giá).

double convert(double amount, double rate) {
    return amount * rate;
}
int main() {
    cout << convert(100, 24500) << " VND\n";  // 100 USD -> VND
}

Đệ quy: Tháp Hà Nội

In các bước chuyển n đĩa từ cột A sang C dùng B.

void hanoi(int n, char from, char to, char via) {
    if (n == 0) return;
    hanoi(n-1, from, via, to);
    cout << "Chuyen dia " << n << ": " << from << "->" << to << endl;
    hanoi(n-1, via, to, from);
}
int main() { hanoi(3, 'A', 'C', 'B'); }

💡 Mẹo & lưu ý

  • Tránh biến toàn cục — truyền qua tham số.
  • Đệ quy sâu > ~10^5 có thể tràn stack — chuyển sang lặp hoặc dùng memoization.
  • Const-correctness: đánh dấu const mọi chỗ không cần sửa.