Xem thêm

Hằng số trong C++ (Constants)

Huy Erick
Giới thiệu Trong bài học trước, bạn đã được tìm hiểu về các thao tác nhập xuất và định dạng dữ liệu trong C++. Bây giờ, chúng ta sẽ cùng nhau khám phá một khái...

Giới thiệu

Trong bài học trước, bạn đã được tìm hiểu về các thao tác nhập xuất và định dạng dữ liệu trong C++. Bây giờ, chúng ta sẽ cùng nhau khám phá một khái niệm mới quan trọng trong lập trình - Hằng số trong C++.

Nội dung

Để hiểu rõ bài viết này, bạn nên có kiến thức cơ bản về các phần sau:

  • Biến trong C++
  • Kiểu dữ liệu cơ bản trong C++

Trong bài viết này, chúng ta sẽ tìm hiểu về các vấn đề sau:

  • Tổng quan về hằng số
  • Hằng số với từ khóa const
  • Hằng số với chỉ thị tiền xử lý #define
  • Nơi nên định nghĩa hằng số

Tổng quan về hằng số

Trong bài học trước, bạn đã biết biến là tên của một vùng bộ nhớ RAM dùng để lưu trữ thông tin. Bạn có thể gán, thay đổi và lấy thông tin từ biến trong quá trình chạy chương trình.

Tuy nhiên, trong thực tế, có những đối tượng mà giá trị của chúng không bao giờ thay đổi. Ví dụ: PI = 3.14159, tốc độ âm thanh v = 343.2 m/s, vv. Nếu bạn lưu các giá trị này vào biến, rất có khả năng chúng sẽ bị thay đổi trong quá trình chạy chương trình. Đó là lý do tại sao khái niệm "hằng số" trong lập trình ra đời.

Hằng số với từ khóa const

Khai báo một hằng số trong C++

Để khai báo một hằng số trong C++, bạn sử dụng từ khóa const trước hoặc sau kiểu dữ liệu của biến.

Ví dụ:

const double PI{ 3.14159 }; // Cách thông dụng
double const SPEED_OF_SOUND{ 343.2 }; // Cách ít được sử dụng

Chú ý: Hằng số phải được khởi tạo trong lúc khai báo, và giá trị của hằng số sẽ không thể thay đổi trong suốt chương trình.

const double PI; // Sai vì hằng số phải được khởi tạo khi khai báo
const double PI{ 3.14159 }; // Khởi tạo hằng số PI
PI = 3; // Sai vì hằng số không thể thay đổi giá trị

Hằng số có thể được khởi tạo giá trị từ một biến thông thường:

int nHeight = 169;
const int HEIGHT{ nHeight };

Hằng số cũng có thể được sử dụng làm tham số của một hàm. Cách sử dụng này rất phổ biến và hữu ích, với hai mục đích chính:

  1. Giúp lập trình viên biết rằng tham số hằng sẽ không bị thay đổi giá trị sau khi hàm được gọi.
  2. Đảm bảo tham số hằng sẽ không bị thay đổi giá trị bên trong hàm.

Ví dụ:

// Hàm in năm sinh, với tham số hằng nYear
void printYearOfBirth(const int nYear) {
    cout << "Year of birth: " << nYear << endl;
}

Hằng số với chỉ thị tiền xử lý #define

Ngoài cách sử dụng từ khóa const, C++ cũng cho phép sử dụng chỉ thị tiền xử lý #define để định nghĩa một macro sử dụng như một hằng số. Phương pháp này thường được sử dụng trong những hệ thống cũ, nhưng hiện nay ít được sử dụng hơn vì những hạn chế của nó.

Cú pháp khai báo:

#define identifier substitution_text

Khi tiền xử lý gặp chỉ thị này, mọi lần xuất hiện của identifier trong chương trình sẽ được thay thế bằng substitution_text. Thông thường, identifier sẽ được viết hoa toàn bộ và sử dụng gạch dưới _ để thay thế khoảng trắng.

Ví dụ:

#include 
using namespace std;

// Định nghĩa một macro bằng chỉ thị tiền xử lý #define
#define YEAR_OF_BIRTH 2016

int main() {
    cout << "Year of birth: " << YEAR_OF_BIRTH << endl;

    // Khởi tạo một biến integer với giá trị 2016
    int nYear{ YEAR_OF_BIRTH };
    return 0;
}

Trong chương trình trên, khi bạn biên dịch, tiền xử lý sẽ thay thế tất cả các macro YEAR_OF_BIRTH thành giá trị 2016. Sau đó, chương trình sẽ được biên dịch bình thường.

Cách sử dụng tiền xử lý #define có nhiều ưu điểm:

  • Trực quan hơn: khi nhìn vào một tiền xử lý #define, bạn có thể biết mục đích của nó thông qua tên.
  • Tránh "hardcode": khi tiền xử lý #define được sử dụng ở nhiều nơi, bạn chỉ cần thay đổi giá trị ở nơi khai báo, các nơi khác sẽ tự động cập nhật giá trị.

Tuy vậy, bạn nên hạn chế hoặc không nên sử dụng tiền xử lý #define làm hằng số cho chương trình vì:

  • Gây khó khăn khi gỡ lỗi chương trình: Macro là chỉ thị tiền xử lý, khi chương trình biên dịch, tiền xử lý sẽ thay thế tất cả các macro trong chương trình bằng giá trị của chúng. Vì vậy, khi bạn gỡ lỗi chương trình, các macro này sẽ không hiển thị giá trị mà chúng đang giữ, điều này làm khó khăn cho việc gỡ lỗi.
  • Macro luôn có phạm vi toàn cục: Một macro được #define trong một khối lệnh sẽ ảnh hưởng đến một macro #define trong khối lệnh khác nếu chúng cùng tên.

Ví dụ:

#include 
using namespace std;

// Định nghĩa một macro bằng chỉ thị tiền xử lý #define
#define YEAR_OF_BIRTH 2016

int main() {
    cout << "Year of birth: " << YEAR_OF_BIRTH << endl;

    // Định nghĩa một macro trùng tên
    #define YEAR_OF_BIRTH 20

    printYearOfBirth();
    return 0;
}

// Định nghĩa hàm
void printYearOfBirth() {
    cout << "Year of birth: " << YEAR_OF_BIRTH << endl;
}

Trong chương trình trên, macro YEAR_OF_BIRTH đã bị định nghĩa lại trong thân hàm main(). Điều này dẫn đến khi gọi hàm printYearOfBirth(), kết quả in ra đã thay đổi từ 2016 thành 20.

Chú ý: Nên sử dụng hằng số với từ khóa const thay vì chỉ thị tiền xử lý #define.

Nên định nghĩa hằng số ở đâu

Một hằng số thường được sử dụng ở mọi nơi trong chương trình, vì giá trị của nó là không thay đổi (ví dụ: các hằng số toán học, vật lý, hóa học, vv.). Việc định nghĩa một hằng số ở nhiều nơi trong chương trình là một điều không nên. Vì vậy, bạn nên định nghĩa hằng số ở một nơi duy nhất và sử dụng nó trong toàn bộ chương trình.

Có nhiều cách để thực hiện việc này, mình sẽ đề cập đến 2 cách thường được sử dụng:

Cách 1: Định nghĩa hằng số ở phạm vi toàn cục

Trong những chương trình đơn giản, bạn có thể định nghĩa một hằng số ở phạm vi toàn cục để có thể sử dụng ở mọi nơi trong file của bạn.

Ví dụ:

#include 
using namespace std;

// Định nghĩa hằng số phạm vi toàn cục
const double PI{ 3.14159 };

// Định nghĩa hàm in PI
void printPI() {
    cout << "PI = " << PI << endl;
}

int main() {
    cout << "PI = " << PI << endl;
    return 0;
}

Cách 2: Sử dụng header file

Trong những chương trình phức tạp hơn, bạn có thể thực hiện theo các bước sau:

  1. Tạo một header file định nghĩa các hằng số để có thể sử dụng ở mọi nơi trong chương trình.
  2. Tạo một namespace bên trong file header để phân biệt nếu có một biến khác trùng tên với hằng số của bạn.
  3. Định nghĩa tất cả các hằng số bên trong namespace.
  4. Include file header ở nơi bạn cần sử dụng hằng số.

Ví dụ:

File Constants.h

#ifndef _CONSTANTS_
#define _CONSTANTS_

// Định nghĩa namespace chứa các hằng số
namespace constants {
    const double PI{ 3.14159 };
    const double SPEED_OF_SOUND{ 343.2 }; // Tốc độ âm thanh 343.2 m/s
    const int YEAR_OF_BIRTH{ 2016 };
    // ...
}

#endif // !_CONSTANTS_

File main.cpp

#include 
#include "Constants.h" // Include header file
using namespace std;

//using namespace constants;

int main() {
    // Sử dụng toán tử phân giải phạm vi :: để truy cập hằng số từ namespace
    cout << "PI = " << constants::PI << endl;
    cout << "Year of birth: " << constants::YEAR_OF_BIRTH << endl;
    return 0;
}

Kết luận

Qua bài viết này, chúng ta đã tìm hiểu về các loại hằng số trong C++ và biết cách khởi tạo và sử dụng hằng số một cách hiệu quả.

Trong bài viết tiếp theo, chúng ta sẽ học về toán tử cơ bản trong C++, vốn là nền tảng để bạn có thể giải quyết các bài toán trong lập trình.

Cảm ơn các bạn đã theo dõi bài viết. Hãy để lại bình luận hoặc góp ý của mình để chúng tôi cải thiện bài viết. Đừng quên "Luyện tập - Thử thách - Không ngại khó".

Thảo luận

Nếu bạn gặp khó khăn hoặc có bất kỳ câu hỏi nào liên quan đến khóa học, đừng ngần ngại đặt câu hỏi trong phần bình luận bên dưới hoặc trong mục Hỏi & Đáp trên thư viện Howkteam.com để nhận được sự trợ giúp từ cộng đồng.

1