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ế

 

pdf35 trang | Chuyên mục: C/C++ | Chia sẻ: tuando | Lượt xem: 534 | Lượt tải: 0download
Tóm tắt nội dung Bài giảng Lập trình hướng đối tượng - Chương 3: Mảng, Con trỏ và tham chiếu, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
" << 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:

  • pdfbai_giang_lap_trinh_huong_doi_tuong_tap_1_chuong_3_mang_con.pdf