Bài giảng Ngôn ngữ lập trình C/C++ - Phạm Hồng Thái

Từ đó lập trình hướng đối tượng được xây dựng dựa trên đặc trưng chính là

khái niệm đóng gói. Đóng gói là khái niệm trung tâm của phương pháp lập trình

hướng đối tượng, trong đó dữ liệu và các thao tác xử lý nó sẽ được qui định trước

và "đóng" thành một "gói" thống nhất, riêng biệt với các dữ liệu khác tạo thành kiểu

dữ liệu với tên gọi là các lớp. Như vậy một lớp không chỉ chứa dữ liệu bình thường

như các kiểu dữ liệu khác mà còn chứa các thao tác để xử lý dữ liệu này. Các thao

tác được khai báo trong gói dữ liệu nào chỉ xử lý dữ liệu trong gói đó và ngược lại

dữ liệu trong một gói chỉ bị tác động, xử lý bởi thao tác đã khai báo trong gói đó.

Điều này tạo tính tập trung cao khi lập trình, mọi đối tượng trong một lớp sẽ chứa

cùng loại dữ liệu được chỉ định và cùng được xử lý bởi các thao tác như nhau. Mọi

lập trình viên khi làm việc với dữ liệu trong một gói đều sử dụng các thao tác như

nhau để xử lý dữ liệu trong gói đó. C++ cung cấp cách thức để tạo một cấu trúc dữ

liệu mới thể hiện các gói nói trên, cấu trúc dữ liệu này được gọi là lớp.

pdf308 trang | Chia sẻ: lethuong715 | Lượt xem: 847 | Lượt tải: 0download
Bạn đang xem trước 20 trang mẫu tài liệu Bài giảng Ngôn ngữ lập trình C/C++ - Phạm Hồng Thái, để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên
IV. TỔ CHỨC CHƯƠNG TRÌNH 
1. Các loại biến và phạm vi 
a. Biến cục bộ 
Là các biến được khai báo trong thân của hàm và chỉ có tác dụng trong hàm này, 
kể cả các biến khai báo trong hàm main() cũng chỉ có tác dụng riêng trong hàm main(). 
Từ đó, tên biến trong các hàm là được phép trùng nhau. Các biến của hàm nào sẽ chỉ 
 127
Chương 4. Hàm và chương trình 
tồn tại trong thời gian hàm đó hoạt động. Khi bắt đầu hoạt động các biến này được tự 
động sinh ra và đến khi hàm kết thúc các biến này sẽ mất đi. Tóm lại, một hàm được 
xem như một đơn vị độc lập, khép kín. 
Tham đối của các hàm cũng được xem như biến cục bộ. 
Ví dụ 1 : Dưới đây ta nhắc lại một chương trình nhỏ gồm 3 hàm: luỹ thừa, xoá màn 
hình và main(). Mục đích để minh hoạ biến cục bộ. 
float luythua(float x, int n) // hàm trả giá trị xn
{ 
 int i ; 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
 return kq; 
} 
void xmh(int n) // xoá màn hình n lần 
{ 
 int i; 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 float x; int n; 
 cout > x >> n; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, n); // in xn
} 
Qua ví dụ trên ta thấy các biến i, đối n được khai báo trong hai hàm: luythua() và 
xmh(). kq được khai báo trong luythua và main(), ngoài ra các biến x và n trùng với đối 
của hàm luythua(). Tuy nhiên, tất cả khai báo trên đều hợp lệ và đều được xem như 
khác nhau. Có thể giải thích như sau: 
− Tất cả các biến trên đều cục bộ trong hàm nó được khai báo. 
 128 
Chương 4. Hàm và chương trình 
− x và n trong main() có thời gian hoạt động dài nhất: trong suốt quá trình chạy 
chương trình. Chúng chỉ mất đi khi chương trình chấm dứt. Đối x và n trong 
luythua() chỉ tạm thời được tạo ra khi hàm luythua() được gọi đến và độc lập 
với x, n trong main(), nói cách khác tại thời điểm đó trong bộ nhớ có hai biến 
x và hai biến n. Khi hàm luythua chay xong biến x và n của nó tự động biến 
mất. 
− Tương tự 2 đối n, 2 biến i trong luythua() và xoá màn hình cũng độc lập với 
nhau, chúng chỉ được tạo và tồn tại trong thời gian hàm của chúng được gọi và 
hoạt động. 
b. Biến ngoài 
Là các biến được khai báo bên ngoài của tất cả các hàm. Vị trí khai báo của 
chúng có thể từ đầu văn bản chương trình hoặc tại một một vị trí bất kỳ nào đó giữa 
văn bản chương trình. Thời gian tồn tại của chúng là từ lúc chương trình bắt đầu chạy 
đến khi kết thúc chương trình giống như các biến trong hàm main(). Tuy nhiên về 
phạm vi tác dụng của chúng là bắt đầu từ điểm khai báo chúng đến hết chương trình, 
tức tất cả các hàm khai báo sau này đều có thể sử dụng và thay đổi giá trị của chúng. 
Như vậy các biến ngoài được khai báo từ đầu chương trình sẽ có tác dụng lên toàn bộ 
chương trình. Tất cả các hàm đều sử dụng được các biến này nếu trong hàm đó không 
có biến khai báo trùng tên. Một hàm nếu có biến trùng tên với biến ngoài thì biến ngoài 
bị che đối với hàm này. Có nghĩa nếu i được khai báo như một biến ngoài và ngoài ra 
trong một hàm nào đó cũng có biến i thì như vậy có 2 biến i độc lập với nhau và khi 
hàm truy nhập đến i thì có nghĩa là i của hàm chứ không phải i của biến ngoài. 
Dưới đây là ví dụ minh hoạ cho các giải thích trên. 
Ví dụ 2 : Chúng ta xét lại các hàm luythua() và xmh(). Chú ý rằng trong cả hai hàm này 
đều có biến i, vì vậy chúng ta có thể khai báo i như một biến ngoài (để dùng chung cho 
luythua() và xmh()), ngoài ra x, n cũng có thể được khai báo như biến ngoài. Cụ thể: 
#include 
#include 
float x; int n; int i ; 
float luythua(float x, int n) 
{ 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
} 
 129
Chương 4. Hàm và chương trình 
void xmh() 
{ 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 cout > x >> n; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, n); // in xn
} 
Trong ví dụ này ta thấy các biến x, n, i đều là các biến ngoài. Khi ta muốn sử 
dụng biến ngoài ví dụ i, thì biến i sẽ không được khai báo trong hàm sử dụng nó. 
Chẳng hạn, luythua() và xmh() đều sử dụng i cho vòng lặp for của mình và nó không 
được khai báo lại trong 2 hàm này. Các đối x và n trong luythua() là độc lập với biến 
ngoài x và n. Trong luythua() khi sử dụng đến x và n (ví dụ câu lệnh kq *= x) thì đây là 
x của hàm chứ không phải biến ngoài, trong khi trong main() không có khai báo về x 
và n nên ví dụ câu lệnh cout << luythua(x, n); là sử dụng x, n của biến ngoài. 
Nói chung trong 2 ví dụ trên chương trình đều chạy tốt và như nhau. Tuy nhiên, 
việc khai báo khác nhau như vậy có ảnh hưởng hoặc gây nhầm lẫn gì cho người lập 
trình ? Liệu chúng ta có nên tự đặt ra một nguyên tắc nào đó trong khai báo biến ngoài 
và biến cục bộ để tránh những nhầm lẫn có thể xảy ra. Chúng ta hãy xét tiếp cũng ví dụ 
trên nhưng thay đổi một số khai báo và tính 23 (có thể bỏ bớt biến n) như sau: 
#include 
#include 
float x; int i ; // không dùng n 
float luythua(float x, int n) 
{ 
 float kq = 1; 
 for (i=1; i<=n; i++) kq *= x; 
} 
void xmh() 
{ 
 130 
Chương 4. Hàm và chương trình 
 for (i=1; i<=n; i++) clrscr(); 
} 
main() 
{ 
 x = 2; 
 i = 3; 
 xmh(5); // xoá màn hình 5 lần 
 cout << luythua(x, i); // in xi, kết quả x = 23 = 8 ? 
} 
Nhìn vào hàm main() ta thấy giá trị 23 được tính bằng cách đặt x = 2, i = 3 và gọi 
hàm luythua(x,i). Kết quả ta mong muốn sẽ là giá trị 8 hiện ra màn hình, tuy nhiên 
không đúng như vậy. Trước khi in kết quả này ra màn hình hàm xmh() đã được gọi đến 
để xoá màn hình. Hàm này sử dụng một biến ngoài i để làm biến đếm cho mình trong 
vòng lặp for và sau khi ra khỏi for (cũng là kết thúc xmh()) i nhận giá trị 6. Biến i 
ngoài này lại được sử dụng trong lời gọi luythua(x,i) của hàm main(), tức tại thời điểm 
này x = 2 và i = 6, kết quả in ra màn hình sẽ là 26 = 64 thay vì 8 như mong muốn. 
Tóm lại "điểm yếu" dẫn đến sai sót của chương trình trên là ở chỗ lập trình viên 
đã "tranh thủ" sử dụng biến i cho 2 hàm xmh() và main() (bằng cách khai báo nó như 
biến ngoài) nhưng lại với mục đích khác nhau. Do vậy sau khi chạy xong hàm xmh() i 
bị thay đổi khác với giá trị i được khởi tạo lúc ban đầu. Để khắc phục lỗi trong chương 
trình trên ta cần khai báo lại biến i: hoặc trong main() khai báo thêm i (nó sẽ che biến i 
ngoài), hoặc trong cả hai xmh() và main() đều có biến i (cục bộ trong từng hàm). 
Từ đó, ta nên đề ra một vài nguyên tắc lập trình sao cho nó có thể tránh được 
những lỗi không đáng có như vậy: 
• nếu một biến chỉ sử dụng vì mục đích riêng của một hàm thì nên khai báo 
biến đó như biến cục bộ trong hàm. Ví dụ các biến đếm của vòng lặp, thông 
thường chúng chỉ được sử dụng thậm chí chỉ riêng trong vòng lặp chứ cũng 
chưa phải cho toàn bộ cả hàm, vì vậy không nên khai báo chúng như biến 
ngoài. Những biến cục bộ này sau khi hàm kết thúc chúng cũng sẽ kết thúc, 
không gây ảnh hưởng đến bất kỳ hàm nào khác. Một đặc điểm có lợi nữa cho 
khai báo cục bộ là chúng tạo cho hàm tính cách hoàn chỉnh, độc lập với mọi 
hàm khác, chương trình khác. Ví dụ hàm xmh() có thể mang qua chạy ở 
chương trình khác mà không phải sửa chữa gì nếu i đã được khai báo bên 
trong hàm. Trong khi ở ví dụ này hàm xmh() vẫn hoạt động được nhưng trong 
chương trình khác nếu không có i như một biến ngoài (để xmh() sử dụng) thì 
hàm sẽ gây lỗi. 
 131
Chương 4. Hàm và chương trình 
• với các biến mang tính chất sử dụng chung rõ nét (đặc biệt với những biến 
kích thước lớn) mà nhiều hàm cùng sử dụng chúng với mục đích giống nhau 
thì nên khai báo chúng như biến ngoài. Điều này tiết kiệm được thời gian cho 
người lập trình vì không phải khai báo chúng nhiều lần trong nhiều hàm, tiết 
kiệm bộ nhớ vì không phải tạo chúng tạm thời mỗi khi chạy các hàm, tiết 
kiệm được thời gian chạy chương trình vì không phải tổ chức bộ nhớ để lưu 
trữ và giải phóng chúng. Ví dụ trong chương trình quản lý sinh viên (chương 
6), biến sinh viên được dùng chung và thống nhất trong hầu hết các hàm (xem, 
xoá, sửa, bổ sung, thống kê ) nên có thể khai báo chúng như biến ngoài, 
điều này cũng tăng tính thống nhất của chương trình (mọi biến sinh viên là 
như nhau cho mọi hàm con của chương trình). 
Tóm lại, nguyên tắc tổng quát nhất là cố gắng tạo hàm một cách độc lập, khép 
kín, không chịu ảnh hưởng của các hàm khác và không gây ảnh hưởng đến hoạt động 
của các hàm khác đến mức có thể. 
2. Biến với mục đích đặc biệt 
a. Biến hằng và từ khoá const 
Để sử dụng hằng có thể khai báo thêm từ khoá const trước khai báo biến. Phạm vi 
và miền tác dụng cũng như biến, có nghĩa biến hằng cũng có thể ở dạng cục bộ hoặc 
toàn thể. Biến hằng luôn luôn được khởi tạo trước. 
Có thể khai báo từ khoá const trước các tham đối hình thức để không cho phép 
thay đổi giá trị của các biến ngoài (đặc biệt đối với với mảng và xâu kí tự, vì bản thân 
các biến này được xem như con trỏ do đó hàm có thể thay đổi được giá trị của các biến 
ngoài truyền cho hàm này). 
Ví dụ sau thể hiện hằng cũng có thể được khai báo ở các phạm vi khác nhau. 
const int MAX = 30; // toàn thể 
void vidu(const int *p) // cục bộ 
{ 
const MAX = 10; // cục bộ 
} 
void main() 
{ 
const MAX = 5; // cục bộ 
 132 
Chương 4. Hàm và chương trình 
} 
Trong Turbo C, BorlandC và các chương trình dịch khác có nhiều hằng số khai 
báo sẵn trong tệp values.h như MAXINT, M_PI hoặc các hằng đồ hoạ trong graphics.h 
như WHITE, RED,  
b. Biến tĩnh và từ khoá static 
Được khai báo bằng từ khoá static. Là biến cục bộ nhưng vẫn giữ giá trị sau khi 
ra khỏi hàm. Phạm vi tác dụng như biến cục bộ, nghĩa là nó chỉ được sử dụng trong 
hàm khai báo nó. Tuy nhiên thời gian tác dụng được xem như biến toàn thể, tức sau khi 
hàm thực hiện xong biến vẫn còn tồn tại và vẫn lưu lại giá trị sau khi ra khỏi hàm. Giá 
trị này này được tiếp tục sử dụng khi hàm được gọi lại, tức biến static chỉ được khởi 
đầu một lần trong lần chạy hàm đầu tiên. Nếu không khởi tạo, C++ tự động gán giá trị 
0 (ngầm định = 0). Ví dụ: 
int i = 1; 
void bp() 
{ 
static int lanthu 

File đính kèm:

  • pdfNGon ngu lap trinh CC.pdf