Tải bản đầy đủ (.pdf) (35 trang)

Mảng con trỏ và tham chiếu

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (61.88 KB, 35 trang )




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ế







Chöông 3
Maûng, Con troû, Tham chieáu



68
68











































Chương 3
Mảng, Con trỏ, Tham chiếu



69
69
I/ Mảng các đối tượng
Các đối tượng chính là các biến , có các khả năng và thuộc tính như các biến thông
thường khác. Do đó, các đối tượng có thể tổ chức thành mảng.

Cú pháp khai báo một
mảng các đối tượng
hoàn toàn giống như ngôn ngữ C.
Việc truy cập mảng các đối tượng cũng giống như mảng của các loại biến khác.

Ví dụ 1.1
Mảng các đối tượng
#include <iostream.h>

class samp {
int a;
public:
void set_a(int n) { a = n; }
int get_a() { return a; }
};

int main()
{

samp ob[4]
; // khai báo mảng đối tượng
int i;

for(i=0; i<4; i++)
ob[i].
set_a(i); // truy cập mảng đối tượng
for(i=0; i<4; i++) cout << ob[i].get_a( );
return 0;
}



Nếu kiểu lớp
có hàm tạo, thì mảng đối tượng có thể được khởi đầu
.

Ví dụ 1.2
// Initialize an array.
#include <iostream.h>
class samp {
int a;
public:

samp(int n) { a = n; }
Chương 3
Mảng, Con trỏ, Tham chiếu




70
70
int get_a() { return a; }
};

int main()
{
samp
ob[4] = { -1, -2, -3, -4 }
;
int i;

for(i=0; i<4; i++) cout << ob[i].get_a() << ' ';
return 0;
}

@ Một cách viết khác (dài hơn)
samp ob[4] = { samp(-1), samp(- 2), samp(-3), samp(- 4) };

@ Cách khởi đầu ở trên chỉ làm việc với các
mảng có hàm tạo chỉ nhận một đối số
.



Khởi đầu mảng đối tượng nhiều chiều.

Ví dụ 1.3
// Create a two-dimensional array of objects.
#include <iostream.h>


class samp {
int a;
public:
samp(int n) { a = n; }
int get_a() { return a; }
};

int main()
{
samp
ob[4][2] = { 1, 2,
3, 4,
5, 6,
7, 8 };

int i;
Chương 3
Mảng, Con trỏ, Tham chiếu



71
71
for(i=0; i<4; i++) {
cout <<
ob[i][0].
get_a() << ' ';
cout <<
ob[i][1].

get_a() << "\n";
}
return 0;
}


Khi khởi đầu một
mảng đối tượng có hàm tạo nhận nhiều đối số
, cần phải dùng
dạng khởi đầu khác.

Vídụ 1.4
#include <iostream.h>

class samp {
int a, b;
public:

samp(int n, int m)
{ a = n; b = m; }
int get_a() { return a; }
int get_b() { return b; }
};

int main()
{
samp
ob[4][2] = { samp(1, 2), samp(3, 4),
samp(5, 6), samp(7, 8),
samp(9, 10), samp(11, 12),

samp(13, 14), samp(15, 16) }
;
int i;

for(i=0; i<4; i++) {
cout <<
ob[i][0].
get_a() << ' ';
cout <<
ob[i][0].
get_b() << "\n";
cout <<
ob[i][1].
get_a() << ' ';
cout <<
ob[i][1].
get_b() << "\n";
}
return 0;
}
Chương 3
Mảng, Con trỏ, Tham chiếu



72
72

Bài tập I


1. Dùng khai báo lớp sau đây để tạo mảng 10 phần tử và khởi đầu phần tử ch với các
giá trò từ A đến J. Hãy chứng tỏ mảng chứa các giá trò này.
#include <iostream.h>

class letters {
char ch;
public:
letters(char c) { ch = c; }
char get_ch() { return ch; }
};

2. Dùng khai báo lớp sau đây để tạo mảng 10 phần tử và khởi đầu num với các giá
trò từ 1 đến 10 và hãy khởi đầu spr đối với bình phương của num.

#include <iostream.h>

class squares {
int num, sqr;
public:
squares(int a, int b) { num = a; sqr = b; }
void show() {cout << num << ' ' << sqr << "\n"; }
};


II/ Con trỏ đối tượng
Các đối tượng có thể được truy cập thông qua con trỏ, toán tử -> sẽ được dùng.

Khai báo một con trỏ đối tượng
giống như khai báo một con trỏ hướng về kiểu biến
bất kỳ. Ví dụ samp *p;


Để có
điạ chỉ của một đối tượng
, dùng toán tử & đặt trước đối tượng. Ví dụ
p = &ob;


Chương 3
Mảng, Con trỏ, Tham chiếu



73
73
Ví dụ 2.1
#include <iostream.h>

class myclass {
int a;
public:
myclass(int x); // constructor
int get();
};

myclass::myclass(int x)
{
a = x;
}

int myclass::get()

{
return a;
}

int main()
{
myclass ob(120); // create object

myclass *p
; // create pointer to object


p = &ob
; // put address of ob into p

cout << "Value using object: " << ob.get() << "\n" ;
cout << "Value using pointer: " <<
p->get()
;

return 0;
}


@ Việc tạo ra một con trỏ đối tượng
không tạo ra một đối tượng
, nó chỉ tạo ra một
con trỏ trỏ về đối tượng.



Chương 3
Mảng, Con trỏ, Tham chiếu



74
74

Số học con trỏ :
+ Khi tăng
con trỏ đối tượng
, nó sẽ trỏ đến đối tượng tiếp theo.
+ Khi giảm
con trỏ đối tượng
, nó sẽ trỏ đến đối tượng đứng trước.


Ví dụ 2.2
// Pointers to objects.
#include <iostream.h>

class samp {
int a, b;
public:

samp(int n, int m)
{ a = n; b = m; }
int get_a() { return a; }
int get_b() { return b; }
};


int main()
{
samp ob[4] = {
samp(1, 2),
samp(3, 4),
samp(5, 6),
samp(7, 8)
};
int i;

samp *p;

p = ob
; // get starting address of array

for(i=0; i<4; i++) {
cout << p->get_a() << ' ';
cout << p->get_b() << "\n";

p++
; // advance to next object
}

return 0;
}
Chương 3
Mảng, Con trỏ, Tham chiếu




75
75

Bài tập II


1. Hãy viết lại ví dụ 2.2 chương 3 để cho nó hiển thò nội dung của mảng ob theo thứ
tự ngược lại.

2. Hãy viết lại ví dụ 1.3 chương 3 để truy cập mảng hai chiều qua con trỏ.


III/ Con trỏ this
this
là con trỏ được truyền tự động cho bất kỳ hàm thành viên nào khi được gọi và
nó là con trỏ tới đối tượng tạo ra lời gọi hàm.

Ví dụ, cho câu lệnh ob.f1() ; // ob là đối tượng

Hàm f1() tự động được truyền con trỏ ob là đối tượng tạo ra lời gọi hàm. Con trỏ này
được xem là
this
.

Chỉ có các hàm thành viên được truyền con trỏ this.
Hàm friend không có con trỏ
this
.
Con trỏ this có nhiều sử dụng, kể cả việc giúp quá tải các toán tử.



Khi một hàm thành viên tham chiếu một hàm thành viên khác của lớp, nó thực
hiện mà không xác đònh tham chiếu với hoặc
một lớp
hoặc
một đặc tả đối tượng
.

Ví dụ 3.1
// Demonstrate the
this
pointer.
#include <iostream.h>
#include <string.h>

class inventory {
char item[20];
double cost;
int on_hand;
public:
inventory(char *i, double c, int o)
Chương 3
Mảng, Con trỏ, Tham chiếu



76
76
{

//
tham chiếu trực tiếp các biến item[], cost, on_hand
strcpy(item, i);
cost = c;
on_hand = o;
}
void show();
};

void inventory::show()
{
cout << item;
cout << ": $" << cost;
cout << " On hand: " << on_hand << "\n";
}

int main()
{
inventory ob("wrench", 4.95, 4);

ob.show();
return 0;
}



Khi một hàm thành viên được gọi,
nó tự động được truyền con trỏ this trỏ về đối
tượng tạo ra lời gọi
. Chương trình có thể viết lại :


Ví dụ 3.2
#include <iostream.h>
#include <string.h>

class inventory { // Demonstrate the
this
pointer.
char item[20];
double cost;
int on_hand;
public:
inventory(char *i, double c, int o)
Chương 3
Mảng, Con trỏ, Tham chiếu



77
77
{
strcpy(
this->item
, i); // access members

this->cost
= c; // through the this

this->on_hand
= o; // pointer

}
void show();
};

void inventory::show()
{
cout << this->item; // use this to access members
cout << ": $" << this->cost;
cout << " On hand: " << this->on_hand << "\n";
}
int main()
{
inventory ob("wrench", 4.95, 4);

ob.show();
return 0;
}


Bài tập III

Hãy chuyển tất cả các tham chiếu thích hợp đối với các thành viên của lớp thành
tham chiếu con trỏ this.
#include <iostream.h>

class myclass {
int a, b;
public:
myclass(int n, int m) { a = n; b = m; }
int add() { return a+b; }

void show();
};

void myclass::show()
Chương 3
Mảng, Con trỏ, Tham chiếu



78
78
{
int t;

t = add(); // call member function
cout << t << "\n";
}

int main()
{
myclass ob(10, 14);

ob.show();
return 0;
}


IV/ Toán tử new và delete

1/ Toán tử

new
dùng để cấp phát bộ nhớ động và toán tử
delete
dùng giải phóng bộ
nhớ đã cấp phát.

Cú pháp p_var =
new
data_type;

delete
p_var;

data_type
chỉ đònh kiểu đối tượng muốn cấp phát bộ nhớ
p_var
con trỏ tới kiểu đó


Giống như hàm malloc(), nếu không đủ bộ nhớ theo yêu cầu cấp phát thì toán tử
new sẽ trả về con trỏ NULL. Toán tử delete được gọi chỉ với một con trỏ đã được
cấp phát trước đó qua toán tử new. Nếu gọi delete với một con trỏ không hợp lệ, hệ
thống cấp phát sẽ bò hủy, và có thể làm hỏng chương trình.

Các ưu điểm
+ toán tử new tự động cấp phát bộ nhớ để giữ một đối tượng có kiểu được chỉ rõ.
+ toán tử new tự động trả về một con trỏ có kiểu được chỉ rõ.
+ toán tử new và delete có thể được quá tải.
+ có thể khởi đầu đối tượng được cấp phát động.
Chương 3

Mảng, Con trỏ, Tham chiếu



79
79
+ không cần nạp thư viện malloc.h hoặc stdlib.h vào trong chương trình.



Cấp phát bộ nhớ động để giữa một số nguyên

Ví dụ 4.1
// A simple example of new and delete.
#include <iostream.h>

int main()
{
int *p;


p = new int
; // allocate room for an integer
if(!p) {
cout << "Allocation error\n";
return 1;
}

*p = 1000;


cout << "Here is integer at p: " << *p << "\n";


delete p
; // release memory
return 0;
}



Cấp phát động một đối tượng

Ví dụ 4.2
// Allocating dynamic objects.
#include <iostream.h>

class samp {
int i, j;
public:
void set_ij(int a, int b) { i=a; j=b; }
Chương 3
Mảng, Con trỏ, Tham chiếu



80
80
int get_product() { return i*j; }
};


int main()
{
samp *p;


p = new samp
; // allocate object
if(!p) {
cout << "Allocation error\n";
return 1;
}

p->set_ij(4, 5);

cout << "Product is: " << p->get_product() << "\n";

delete p
; // release memory
return 0;
}


Bài tập IVa

1. Hãy viết chương trình sử dụng new để cấp phát động một float, một long và một
char. Cho các biến động này những giá trò và hiển thò. Sau đó, hãy dùng delete giải
phóng tất cả bộ nhớ.

2. Hãy tạo một lớp có chứa tên và số điện thoại của một người. Dùng new để cấp
phát động một đối tượng của lớp này, lưu tên và số điện thoại vào đối tượng đó rồi

hiển thò.



2/ Các đặc điểm của new và delete
+ các đối tượng được cấp phát động một giá trò đầu

p_var = new data_type(
initial_value
)
;

×