Chương 2: Hàm trong C++

Chia sẻ: Men Men | Ngày: | Loại File: DOC | Số trang:31

0
470
lượt xem
96
download

Chương 2: Hàm trong C++

Mô tả tài liệu
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tham khảo tài liệu 'chương 2: hàm trong c++', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:
Lưu

Nội dung Text: Chương 2: Hàm trong C++

  1. chương 2 sẽ lưu trữ địa chỉ của biễn x vào con trỏ px. Hàm trong C++ 1.2. Biến tham chiếu Chương này trình bầy những khả năng mới của C++ trong việc Trong C++ cho phép sử dụng loại biến thứ ba là biến tham xây dựng và sử dụng hàm. Đó là: chiếu. So với 2 loại biến quen biết nói trên, thì biến này có những + Kiểu tham chiếu và việc truyền dữ liệu cho hàm bằng tham đặc điểm sau: chiếu. + Biến tham chiếu không được cấp phát bộ nhớ, không có địa + Đối tham chiếu hằng (const) chỉ riêng. + Đối có giá trị mặc định + Nó dùng làm bí danh cho một biến (kiểu giá trị) nào đó và nó sử dụng vùng nhớ của biến này. Ví dụ câu lệnh: + Hàm trực tuyến float u, v, &r = u ; + Việc định nghĩa chồng các hàm tạo ra các biến thực u, v và biến tham chiếu thực r. Biến r không + Việc định nghĩa chồng các toán tử được cấp phát bộ nhớ, nó là một tên khác (bí danh) của u và nó dùng chung vùng nhớ của biến u. § 1. Biến tham chiếu (Reference variable) Thuật ngữ: Khi r là bí danh (alias) của u thì ta nói r tham chiếu đến biến u. Như vậy 2 thuật ngữ trên được hiểu như nhau. 1.1. Hai loại biến dùng trong C ý nghĩa: Khi r là bí danh của u thì r dùng chung vùng nhớ của u, Trước khi nói đến biến tham chiếu, chúng ta nhắc lại 2 loại dó đó : biến gặp trong C là: + Trong mọi câu lệnh, viết u hay viết r đều có ý nghĩa như Biến giá trị dùng để chứa dữ liệu (nguyên, thực, ký tự, ... ) nhau, vì đều truy nhập đến cùng một vùng nhớ. Biến con trỏ dùng để chứa địa chỉ + Có thể dùng biến tham chiếu để truy nhập đến một biến kiểu Các biến này đều được cung cấp bộ nhớ và có địa chỉ. Ví dụ giá trị. câu lệnh khai báo: Ví dụ: double x , *px; int u, v, &r = u; sẽ tạo ra biến giá trị kiểu double x và biến con trỏ kiểu double px. Biến x có vùng nhớ 8 byte, biến px có vùng nhớ 4 byte (nếu dùng r = 10 ; // u=10 mô hình Large). Biến x dùng để chứa giá trị kiểu double, ví dụ cout
  2. &r; // Cho địa chỉ của u Chương trình dưới đây minh hoạ cách dùng biến tham chiếu đến một phần tử mảng cấu trúc để nhập dữ liệu và thực hiện các phép tính trên các trường của phần tử mảng cấu trúc. Công dụng: Biến tham chiếu thường được sử dụng làm đối của hàm để cho phép hàm truy nhập đến các tham số biến trong #include lời gọi hàm. #include struct TS Vài chú ý về biến tham chiếu: 38 39 { a. Vì biến tham chiếu không có địa chỉ riêng, nó chỉ là bí danh của một biến kiểu giá trị nên trong khai báo phải chỉ rõ nó tham char ht[25]; chiếu đến biến nào. Ví dụ nếu khai báo: float t,l,h,td; double &x ; }; thì Trình biên dịch sẽ báo lỗi: void main() Reference variable ‘x’ must be initialized { b. Biến tham chiếu có thể tham chiếu đến một phần tử mảng, TS ts[10],&h=ts[1]; // h tham chiếu đến ts[1] ví dụ: cout h.t >> h.l >> h.h ; d. Biến tham chiếu có thể tham chiếu đến một hằng. Khi đó nó h.td = h.t + h.l + h.h ; sẽ sử dụng vùng nhớ của hằng và nó có thể làm thay đổi giá trị chứa trong vùng nhớ này. cout
  3. int n = 10 ; việc trực tiếp với các tham số. Phương pháp này có 2 nhược điểm const int &r = n ; // Hằng tham chiếu r tham chiếu đến biến n chính: const int &s=123 ; //Hằng tham chiếu s tham chiếu đến hằng Tốn kém về thời gian và bộ nhớ vì phải tạo ra các bản sao. 123 Không thao tác trực tiếp trên các tham số, vì vậy không làm thay đổi được giá trị các tham số. Sự khác nhau giữa biến và hằng tham chiếu ở chỗ: Không cho phép dùng hằng tham chiếu để làm thay đổi giá trị của vùng nhớ 2.2. Truyền giá trị cho hàm theo tham chiếu mà nó tham chiếu. Trong C++ cung cấp thêm cách truyền dữ liệu cho hàm theo Ví dụ: tham chiếu bằng cách dùng đối là biến tham chiếu hoặc đối là hằng tham chiếu. Cách này có ưu điểm: int y = 12, z ; const int &py=y; // Hằng tham chiếu py tham chiếu đến biến y Không cần tạo ra các bản sao của các tham số, do đó tiết kiệm 40 bộ nhớ và thời gian chạy máy. 41 y++; // Đúng z = 2*py ; // Đúng z = 26 Hàm sẽ thao tác trực tiếp trên vùng nhớ của các tham số, do đó dễ dàng thay đổi giá trị các tham số khi cần. cout
  4. #include nhapds(x,n); #include sapxep(x,n); #include for (i=1;i
  5. void nhapsl(TS *ts,int n) TS ts[100]; { int n,i; for (int i=1;i> ts[i].h ; cin >> dc; ts[i].td = ts[i].t + ts[i].l + ts[i].h ; cout
  6. #include } #include } void nhapmt(float a[20][20], int m, int n) void main() { { for (int i=1 ; i
  7. Ví dụ 1 trình bầy một hàm trả về một tham chiếu đến một TS &f() biến toàn bộ. Do đó có thể dùng hàm để truy nhập đến biến này. { #include return ts; #include } int z ; void main() int &f() // Hàm trả về một bí danh của biến toàn bộ z { { TS &h=f(); // h tham chiếu đến biến ts return z; cout h.t >> h.l >> h.h ; f()=50; // z = 50 h.td = h.t + h.l + h.h ; cout
  8. }; return ts[i]; TS *ts; } void cap_phat_bo_nho_nhapsl(int n) void main() { { int n, i ; ts = new TS[n+1] ; cout > n; { cap_phat_bo_nho_nhapsl(n); cout
  9. Ví dụ hàm delay với đối số mặc định được viết theo một trong nếu ba đối mặc định thì phải là d3, d4, d5 2 cách sau: ... Cách 1 (Không khai báo nguyên mẫu): Các ví dụ sai: void delay(int n=1000) d3 và d5 mặc định (khi đó d4 cũng phải mặc định) { d3 và d4 mặc định (khi đó d5 cũng phải mặc định) for (int i=0 ; i
  10. Có thể dùng các hằng, các biến toàn bộ, các hàm để khởi gán #include cho đối mặc định, ví dụ: void ht(char *dc="HA NOI",int n=10) ; int MAX = 10000; void ht(char *dc , int n ) void f(int n, int m = MAX, int xmax = getmaxx(), { int ymax = getmaxy() ) ; for (int i=0;i
  11. } { void main() int n=1000; { double s=0.0, h=(b-a)/n; int mh=0, mode=0; for (int i=0; i
  12. Tuy nhiên hàm cũng có nhược điểm là làm chậm tốc độ chương #include trình do phải thực hiện một số thao tác có tính thủ tục mỗi khi gọi void main() hàm như: Cấp phát vùng nhớ cho các đối và biến cục bộ, truyền dữ liệu của các tham số cho các đối, giải phóng vùng nhớ trước { khi thoát khỏi hàm. int s ; Các hàm trực tuyến trong C++ cho khả năng khắc phục được s = f(5,6); nhược điểm nói trên. cout
  13. Phương án dùng hàm trực tuyến rút ngắn được thời gian chạy int a[20],b[20],cv[20],dt[20],n; máy nhưng lại làm tăng khối lượng bộ nhớ chương trình (nhất là cout > n; for (int i=1;i
  14. { Định nghĩa chồng (hay còn gọi sự tải bội) các hàm là dùng cùng int a[20],b[20],cv[20],dt[20],n; một tên để định nghĩa các hàm khác nhau. Đây là một mở rộng rất có ý nghĩa của C++. cout > n; FOXPRO,...) mỗi hàm đều phải có một tên phân biệt. Đôi khi đây for (int i=1;i
  15. #include abs(‘A’) ; // Tham số kiểu char, gọi hàm int abs(int i) ; #include abs(3.14F); // Tham số kiểu float, gọi hàm double abs(double int f(int a); d); void f(int a); int f(int a) 6.4. Nên sử dụng phép định nghĩa chồng các hàm như thế nào { Như đã nói ở trên, khi xây dựng cũng như sử dụng các hàm trùng tên, Trình biên dịch C++ đã phải suy đoán và giải quyết return a*a; nhiều trường hợp khá nhập nhằng. Vì vậy không nên lạm dụng } quá đáng khả năng định nghĩa chồng, vì điều đó làm cho chương void f(int a) trình khó kiểm soát và dễ dẫn đến sai sót. Việc định nghĩa chồng sẽ hiệu quả hơn nếu được sử dụng theo các lời khuyên sau: { + Chỉ nên định nghĩa chồng các hàm thực hiện những công việc cout
  16. Để lấy địa chỉ của một hàm, ta khai báo một con trỏ hàm có cout
  17. double s=x[1]; trong đó A, B là các ma trận vuông, C là ma trận chữ nhật. Trong for (int i=2;i ni ; void inmt(MT a,char *ten, int n); cout nd ; for (int i=1;i
  18. cout
  19. s = (p – q*z)/(u + v) { #include x=abs(x); y=abs(y); #include if (x*y==0) return 1; #include while (x!=y) typedef struct if (x>y) x-=y; { else y-=x; int a,b; return x; } PS; } void nhap(PS *p); PS rutgon(PS p) void in(PS p); { int uscln(int x, int y); PS q; PS rutgon(PS p); int x; PS cong(PS p1, PS p2); x=uscln(p.a,p.b); PS tru(PS p1, PS p2); q.a = p.a / x ; PS nhan(PS p1, PS p2); q.b = p.b / x ; PS chia(PS p1, PS p2); return q; void nhap(PS *p) } { PS cong(PS p1, PS p2) int t, m; { printf("\nTu va mau: "); PS q; scanf("%d%d", &t, &m); q.a = p1.a*p2.b + p2.a*p1.b; 70 p->a = t; p->b = m; q.b = p1.b * p2.b ; 71 } return rutgon(q); void in(PS p) } { PS tru(PS p1, PS p2) printf(" %d/%d",p.a,p.b); { } PS q; int uscln(int x, int y) q.a = p1.a*p2.b - p2.a*p1.b;
  20. q.b = p1.b * p2.b ; tu = tru(p,tu) ; return rutgon(q); mau = cong(u,v) ; } s = chia(tu,mau); PS nhan(PS p1, PS p2) printf(“\n Phan so s = “); in(s); { getch(); PS q; } q.a = p1.a * p2.a ; Nhận xét: Việc sử dụng các hàm để thực hiện các phép tính q.b = p1.b * p2.b ; không được tự nhiên và tỏ ra dài dòng. Ví dụ để thực hiện một return rutgon(q); công thức } s = (p - q*z)/(u + v) PS chia(PS p1, PS p2) phải dùng 2 biến trung gian và 4 lời gọi hàm. Câu hỏi đặt ra là có cách nào để chỉ cần viết đúng công thức toán học, mà vẫn nhận { được kết quả mong muốn hay không? PS q; Trong C++ có thể đáp ứng được mong muốn này bằng cách sử q.a = p1.a * p2.b ; dụng các phép toán chuẩn của nó cho các kiểu dữ liệu tự định q.b = p1.b * p2.a ; nghĩa (mảng, cấu trúc, ...). Nói cách khác C++ cho phép dùng các return rutgon(q); phép toán để định nghĩa các hàm, mà ta thường gọi là định nghĩa chồng các toán tử (hay còn gọi: Sự tải bội các toán tử). } 7.3. Cách định nghĩa chồng các toán tử void main() 7.3.1.Tên hàm toán tử: Gồm từ khoá operator và tên phép { toán, ví dụ: PS p, q, z, u, v ; operator+ (định nghĩa chồng phép +) PS tu,mau, s; operator- (định nghĩa chồng phép -) printf("\n Nhap phan so p: "); nhap(&p); 72 7.3.2. Các đối của hàm toán tử: 73 printf("\n Nhap phan so q: ");nhap(&q); a. Với các phép toán có 2 toán hạng , thì hàm toán tử cần có 2 printf("\n Nhap phan so z: ");nhap(&z); đối. Đối thứ nhất ứng với toán hạng thứ nhất, đối thứ hai ứng với printf("\n Nhap phan so u: ");nhap(&u); toán hạng thứ hai. Do vậy, với các phép toán không giao hoán (như printf("\n Nhap phan so v: ");nhap(&v); phép-) thì thứ tự đối là rất quan trọng. tu = nhan(q,z);
Đồng bộ tài khoản