Bài giảng Lập trình hướng đối tượng - Chương 3: Mảng, Con trỏ và tham chiếu
• Mảng các đối tượng
• Con trỏ đối tượng
• Con trỏ this
• Toán tử new và delete
• Tham chiếu (reference)
• Truyền tham chiếu cho đối tượng
• Trả về các tham chiếu
• Các tham chiếu độc lập và các hạn chế
" << i << ", "; cout << "j: " << j << "\n"; swapargs(i, j); cout << "After swapping: "; cout << "i: " << i << ", "; cout << "j: " << j << "\n"; return 0; } void swapargs(int &x, int &y) { int t; t = x; x = y; y = t; } Nếu dùng con trỏ thì hàm swapargs() được viết lại như sau : void swapargs(int *x, int *y) Chương 3 Mảng, Con trỏ, Tham chiếu 89 89 { int t; t = *x; *x = *y; *y = t; } • Hàm round() làm tròn một giá trị double. Giá trị tròn được truyền bởi tham chiếu. Ví dụ 5.4 #include #include void round(double &num); int main() { double i = 100.4; cout << i << " rounded is "; round(i); cout << i << "\n"; i = 10.9; cout << i << " rounded is "; round(i); cout << i << "\n"; return 0; } void round(double &num) { double frac; double val; Chương 3 Mảng, Con trỏ, Tham chiếu 90 90 // decompose num into whole and fractional parts frac = modf(num, &val); if(frac < 0.5) num = val; else num = val+1.0; } Bài tập V 1. Hãy viết hàm neg() để đảo ngược dấu của các tham số nguyên. Theo hai cách : + dùng tham số con trỏ + dùng tham số tham chiếu 2. Tìm lỗi sai trong chương trình sau : // This program has an error. #include void triple(double &num); int main() { double d = 7.0; triple(&d); cout << d; return 0; } // Triple num's value. void triple(double &num) { num = 3 * num; } VI/ Truyền tham chiếu cho đối tượng Chương 3 Mảng, Con trỏ, Tham chiếu 91 91 Trong chương 2, khi một đối tượng được truyền cho một hàm bằng cách dùng cơ chế truyền tham số gọi giá trị, một bản sao đối tượng được tạo ra. Khi hàm trả về, hàm hủy của bản sao đối tượng được gọi, điều này có thể sinh ra những vấn đề nghiêm trọng, chẳng hạn hàm hủy giải phóng bộ nhớ động. Khi truyền đối số bằng tham chiếu, không có bản sao đối tượng được tạo ra, do đó hàm hủy của nó không được gọi khi các hàm trả về. Tuy nhiên, những thay đổi đối với đối tượng ở bên trong hàm có ảnh hưởng đến đối tượng được dùng như đối số. Khi một đối tượng được truyền bởi tham chiếu thì toán tử truy cập thành viên vẫn là toán tử điểm (.) chứ không phải toán tử mũi tên (->) . • Truyền đối tượng bằng giá trị cho hàm được gọi f() Ví dụ 6.1 #include class myclass { int who; public: myclass(int n) { who = n; cout << "Constructing " << who << "\n"; } ~myclass() { cout << "Destructing " << who << "\n"; } int id() { return who; } }; // o is passed by value. void f(myclass o) { cout << "Received " << o.id() << "\n"; } int main() Chương 3 Mảng, Con trỏ, Tham chiếu 92 92 { myclass x(1); f(x); return 0; } Kết quả của chương trình Constructing 1 Received 1 Destructing 1 Destructing 1 Giải thích kết quả ? • Truyền đối tượng bằng tham chiếu cho hàm được gọi f() Ví dụ 6.2 #include class myclass { int who; public: myclass(int n) { who = n; cout << "Constructing " << who << "\n"; } ~myclass() { cout << "Destructing " << who << "\n"; } int id() { return who; } }; // Now, o is passed by reference. void f(myclass &o) { // note that . operator is still used!!! cout << "Received " << o.id() << "\n"; Chương 3 Mảng, Con trỏ, Tham chiếu 93 93 } int main() { myclass x(1); f(x); return 0; } Kết quả của chương trình Constructing 1 Received 1 Destructing 1 Giải thích kết quả ? Bài tập VI 1. Tìm lỗi sai trong chương trình sau. Sửa chương trình theo các dùng tham số tham chiếu. // This program has an error. #include #include #include class strtype { char *p; public: strtype(char *s); ~strtype() { delete [] p; } char *get() { return p; } }; strtype::strtype(char *s) Chương 3 Mảng, Con trỏ, Tham chiếu 94 94 { int l; l = strlen(s)+1; p = new char [l]; if(!p) { cout << "Allocation error\n"; exit(1); } strcpy(p, s); } void show(strtype x) { char *s; s = x.get(); cout << s << "\n"; } int main() { strtype a("Hello"), b("There"); show(a); show(b); return 0; } VII/ Trả về các tham chiếu Chương 3 Mảng, Con trỏ, Tham chiếu 95 95 Một hàm có thể trả về một tham chiếu. Điều này có ích khi quá tải một số loại toán tử nào đó. Một hàm cũng có thể được sử dụng ở bên trái của câu lệnh gán. • Hàm trả về một tham chiếu. Ví dụ 7.1 // A simple example of a function returning a reference. #include int &f(); // return a reference int x; int main() { f() = 100; // assign 100 to reference returned by f() cout << x << "\n"; return 0; } // Return an int reference. int &f() { return x; // returns a reference to x } Bên trong hàm f(), câu lệnh return x không trả về giá trị của biến toàn cục, nhưng nó tự động trả về điạ chỉ của x dưới dạng tham chiếu. • Hàm trả về một tham chiếu, phải cẩn thận khi đối tượng tham chiếu không ra ngoài phạm vi. Chương 3 Mảng, Con trỏ, Tham chiếu 96 96 Ví dụ 7.2 // Return an int reference. int &f() { int x; // x is now a local variable return x; // returns a reference to x } Do x là biến cục bộ, sẽ ra khỏi phạm vi khi f() trả về, nghiã là tham chiếu được trả về bởi f() là vô dụng. • Một ứng dụng của hàm trả về một tham chiếu dùng kiểm tra giới hạn biên của mảng. Ví dụ 7.3 // A simple bounded array example. #include #include class array { int size; char *p; public: array(int num); ~array() { delete [] p; } char &put(int i); char get(int i); }; array::array(int num) { p = new char [num]; if(!p) { cout << "Allocation error\n"; exit(1); } size = num; Chương 3 Mảng, Con trỏ, Tham chiếu 97 97 } // Put something into the array. char &array::put(int i) { if(i=size) { cout << "Bounds error!!!\n"; exit(1); } return p[i]; // return reference to p[i] } // Get something from the array. char array::get(int i) { if(i=size) { cout << "Bounds error!!!\n"; exit(1); } return p[i]; // return character } int main() { array a(10); a.put(3) = 'X'; a.put(2) = 'R'; cout << a.get(3) << a.get(2); cout << "\n"; // now generate run-time boundary error a.put(11) = '!'; return 0; } Chương 3 Mảng, Con trỏ, Tham chiếu 98 98 Bài tập VII 1. Hãy viết chương trình tạo mảng an toàn hai chiều 2x3 các số nguyên. 2. Đoạn chương trình sau có đúng không ? Tại sao ? int &f(); . . . int *x; x = f(); VIII/ Các tham chiếu độc lập và các hạn chế 1/ Tham chiếu độc lập (independent reference) là một biến tham chiếu có tác dụng chỉ là một tên khác cho một biến khác. Tham chiếu độc lập phải được khởi đầu khi khai báo, do các tham chiếu không thể được gán những giá trị mới. Các lập trình viên thường ít sử dụng tham chiếu độc lập. 2/ Một số hạn chế + không thể tham chiếu đến một tham chiếu khác. + không thể có điạ chỉ của tham chiếu. + không thể tạo một mảng các tham chiếu + không thể tham chiếu một trường bit. + các tham chiếu phải được khởi đầu trừ khi chúng là các thành viên của lớp, là các giá trị trả về hoặc là các tham số của hàm. • Chương trình có một tham chiếu độc lập Chương 3 Mảng, Con trỏ, Tham chiếu 99 99 Ví dụ 8.1 #include int main() { int x; int &ref = x; // create an independent reference x = 10; // these two statements ref = 10; // are functionally equivalent ref = 100; // this prints the number 100 twice cout << x << ' ' << ref << "\n"; return 0; } • Một tham chiếu độc lập có thể tham chiếu đến một hằng. Ví dụ 8.2 const int &ref = 10; Bài tập chương 3 Chương 3 Mảng, Con trỏ, Tham chiếu 100 100 1. Cho lớp sau, hãy tạo một mảng hai chiều 3x4 và cho mỗi đối tượng trong mảng một giá trị đầu. class a_type { double a, b; public: a_type(double x, double y) { a = x; b = y; } void show() { cout << a << ' ' << b << "\n"; } }; 2. Hãy thay đổi lời giải đối với bài toán trên để có thể truy cập mảng bằng cách dùng con trỏ. 3. Hãy tạo hàm recip() nhận một tham số tham chiếu double. Hãy cho hàm này thay đổi giá trị của tham số đó. Hãy viết một chương trình cho hàm này hoạt động. 4. Hãy sửa đổi chương trình sau với toán tử new và delete #include #include #include #include class strtype { char *p; int len; public: strtype(char *ptr); ~strtype(); void show(); }; strtype::strtype(char *ptr) { Chương 3 Mảng, Con trỏ, Tham chiếu 101 101 len = strlen(ptr); p = (char *) malloc(len+1); if(!p) { cout << "Allocation error\n"; exit(1); } strcpy(p, ptr); } strtype::~strtype() { cout << "Freeing p\n"; free(p); } void strtype::show() { cout << p << " - length: " << len; cout << "\n"; } int main() { strtype s1("This is a test."), s2("I like C++."); s1.show(); s2.show(); return 0; } 5. Hãy sửa đổi chương trình trên để dùng với tham chiếu
File đính kèm:
- bai_giang_lap_trinh_huong_doi_tuong_tap_1_chuong_3_mang_con.pdf