Biến Local
- Biến local chỉ xuất hiện và tồn tại trong một phạm vi (scope) cụ thể.
- Biến bị tự động hủy khi ra khỏi phạm vi sử dụng.
Nội dung hàm cũng là một phạm vi, vậy nên biến local chỉ tồn tại trong hàm mà biến được khai báo.
#include <iostream>
using namespace std
void Display();
int main()
{
Display();
std::cout << i; // error, bởi vì biến i chỉ tồn tại trong scope khai báo hàm Display
getch();
}
void Display()
{
int i; // biến i bắt đầu được khai báo trong scope
for(i = 0; i < 10; i++)
cout << "in ra i: " << i << endl;
} // điểm kết thúc phạm vi của biến i
Biến Global
- Biến global là biến được khai báo bên ngoài tất cả các hàm, có hiệu lực từ thời điểm nó được khai báo và có có thể sử dụng trong tất cả các hàm trong chương trình.
- Biến global tồn tại đến khi chương trình bị kết thúc.
- Đặc biệt, ta có thể khai báo 1 biến global trong 1 file (.c/.cpp/.h) và truy cập biến này từ 1 file (.c/.cpp/.h) khác. Chú ý, biến phải được khai báo ở cả 2 file và từ khóa extern phải được thêm trong lần khai báo thứ 2.
#include <conio.h>
#include <stdio.h>
int a = 0; // Bien Global a
void Display();
int main()
{
Display();
printf("\na = %d", a);
getch();
}
void Display()
{
for(a = 0; a < 3; a++)
printf("\na = %d", a);
}
Trên là ví dụ về biến a được khai báo global khác với biến a trong vòng lặp
thuộc phạm vi hàm Display()
Biến Extern
- Biến extern tham chiếu của một biến, đã được định nghĩa bên ngoài (ở một file source khác).
- Nó chỉ mang ý nghĩa khai báo (declare) chứ không định nghĩa (define) ( tức là không xin cấp phát thêm bộ nhớ cho biến, bởi biến này đã tồn tại ở dạng toàn cục, được khai báo ở một nơi nào đó ).
- Biến được tham chiếu phải được khai báo ở cấp độ cao nhất (toàn cục), và có thể nằm trong một file khác
Ví dụ: ở một fileA.h, ta có một biến và hàm global như sau:
int bienGlobalA = 0; // implicit definition
void hamGlobalB(); // function prototype (declaration)
int hamGlobalB() {
bienGlobalA = 1;
}
Ví dụ: ở một fileB.h có biến đc khai báo extern như sau:
(Chú ý: từ khóa extern không cho phép gán giá trị ban đầu cho biến, cũng phải thôi, bởi biến này đã coi như được khởi tạo ở một chỗ khác rồi)
extern int GlobalVariable; // implicit definition
void hamGlobalB(); // function prototype (declaration)
void hamGlobalC(){
hamGlobalB()
bienGlobalA = bienGlobalA + 1;
}
Biến Static
Biến tĩnh (static variables) là biến được tạo ra duy nhất một lần khi gọi hàm lần đầu tiên và tiếp tục tồn trong suốt vòng đời của chương trình.
Biến static mang tính chất của 1 biến toàn cục (global), vừa có tính chất của 1 biến cục bộ (local):
Tính chất của biến toàn cục: khi khối lệnh chứa định nghĩa biến đó kết thúc,
biến không bị hủy, vùng nhớ giành cho biến không bị thu hồi. Và nó vẫn nằm
trong vùng nhớ của chương trình.
Và nó được tự động cập nhật khi khối
lệnh đó được gọi lại.
void callStaticV() {
static int bienA = 1000;
bienA++;
std::cout << "bienA: " << bienA;
}
Tính chất của biến cục bộ: biến chỉ có thể được sử dụng trong khối lệnh mà nó
được khai báo.
(
Ví dụ trong khối lệnh trên, nếu gọi biến bienA ngoài scope của hàm
callStaticV, trình biên dịch lập tức sẽ báo lỗi )
void callStaticV() {
static int bien = 1000;
bien++;
std::cout << "bien: " << bien;
}
Dòng static int bien = 1000; chỉ được gọi duy nhất 1 lần.
Sử dụng biến Static khi có nhu cầu giữ giá trị của biến trong chương trình.
Ví dụ: chương trình có chức năng tạo ID không trùng nhau đơn giản, hoặc đếm số lượng các đối tượng được tạo ra của một class trong chương trình.
#include <iostream>
#include <string>
using namespace std;
int taoID()
{
static int s_local_id(0);
++s_local_id;
return s_local_id;
}
int main()
{
int newID1 = taoID();
string strName1("tuan");
int newID2 = taoID();
string strName2("ti");
int newID3 = taoID();
string strName3("tien");
cout << newID1 << " : " + strName1 << endl;
cout << newID2 << " : " + strName2 << endl;
cout << newID3 << " : " + strName3 << endl;
return 0;
}
Biến Constants ( Hằng số trong C++ )
- Để định nghĩa những biến, những thành phần mà giá trị của nó không thay đổi
trong suốt thời gian chạy của chương trình.
Ví dụ: số PI =
3.14,
- Nên định nghĩa hằng số ở một nơi, và sử dụng nó ở toàn chương trình. Việc đặt hằng số ở lẻ tẻ các file, khiến việc bảo trì mai sau rất bất tiện.
Ví dụ: 1 file MyConstants.h riêng để chứa khai báo hằng số cho cả chương trình:
#ifndef _MYCONSTANTS_
#define _MYCONSTANTS_
// Định nghĩa namespace chứa các hằng số
namespace myConstants
{
const double PI{ 3.1416 };
const double TOC_DO_AM_THANH{ 343.2 };
const int SO_GIAY_CUA_1_PHUT{ 60 };
// trong thực tế, bạn sẽ tự biết cần hằng số cho những thông tin nào, bởi nó có ý nghĩa cụ thể với chương trình của bạn.
}
#endif // !_MYCONSTANTS_
Và ta có thể sử dụng nó một cách an toàn và không sợ đụng hàng bởi name space của chúng ta main.cpp
#include <iostream>
#include "MyConstants.h" // include file header hằng số để dùng
using namespace std;
//using namespace myConstants;
int main()
{
cout << "PI = " << myConstants::PI << endl;
return 0;
}
- Có nhiều cách triển khai hằng số trong chương trình:
( 1 ) Hằng số với từ khóa const:
++ Phổ biến và dễ dàng sử dụng vì mang bản chất là một biến thông thường
( 2 ) Hằng số với chỉ thị tiền xử lý #define
Ví dụ:
#include <iostream>
using namespace std;
// Định nghĩa số học sinh tối đa cần lấy thông tin
#define MAX_OF_STUDENT 50
int main()
{
// NHƯỢC ĐIỂM: có thể bị ghi đè bởi define lại cùng tên
#define MAX_OF_STUDENT 51
cout << MAX_OF_STUDENT << endl; // => 51
// làm điều gì đó với MAX_OF_STUDENT, ví dụ nhập thông tin từng học sinh
return 0;
}
++ Ưu điểm: trực quan, và tối ưu hiệu suất hơn, dễ dàng bảo trì, nếu mã nguồn tốt, đôi khi chỉ cần thay đổi giá trị define, chương trình đã được đáp ứng với yêu cầu mới. ( giả dụ, sau này tăng MAX_OF_STUDENT lên 100 )
++ Nhược điểm: các macro luôn có phạm vi toàn cục, ví dụ đoạn mã dưới đây vẫn hợp lệ.
Ví dụ:
#include <iostream>
using namespace std;
void callStaticV() {
static int bien = 1000;
bien++;
qDebug() << "bien: " << bien;
#define MAX_OF_STUDENT 50
#define MAX_OF_STUDENT 51
}
int main()
{
// NHƯỢC ĐIỂM: các macro luôn có phạm vi toàn cục
cout << MAX_OF_STUDENT << endl; // => 51
// làm điều gì đó với MAX_OF_STUDENT, ví dụ nhập thông tin từng học sinh
return 0;
}
TuanTiTien++