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

