– Cấp vùng nhớ cho con trỏ thành viên... • N ếu không có ñịnh nghĩa hàm xây dựng:– Mặc nhiên sẽ tự ñộng có 1 hàm xây dựng không tham số.. – Chỉ có 1 cách khởi tạo ñối tượng theo dạng khô
Trang 1HÀM XÂY D Ự NG, HÀM H Ủ Y VÀ
V
VII Ệ Ệ C C KH KH Ở Ở I T I T Ạ Ạ O O ðỐ ðỐ I T I T ƯỢ ƯỢ NG NG
Ch ươ ng 5
V
VII Ệ Ệ C C KH KH Ở Ở I T I T Ạ Ạ O O ðỐ ðỐ I T I T ƯỢ ƯỢ NG NG
1
N ộ i dung
N ộ i dung
• Hàm xây d ự ng
• Hàm h ủ y
• Hàm xây d ự ng sao chép
• Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
• Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
2
• M ục ñích: kh ởi tạo giá trị ban ñầu cho ñối tượng
– Gán giá trị ñầu cho các thuộc tính.
– Cấp vùng nhớ cho con trỏ thành viên.
class Diem {
int x, y;
class PhanSo {
int tu, mau;
3
int x, y;
public :
Diem( int a)
{ x = y = a; }
Diem( int h, int t)
{ x = h; y=t; }
….
};
int tu, mau;
public : PhanSo() { tu=0; mau=1; } PhanSo( int x) { tu=x; mau=1; } PhanSo( int t, int m) { tu = t; mau=m; }
….
};
• Ví d ụ:
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public :
class Stack {
float * ds;
int soluong;
int vitri;
public : Stack( int max = 10)
Hàm Hàm xây xây d d ự ự ng ng
Cấp vùng nhớ
4
public : SinhVien() { strcpy(mssv,””);
hoten = new char[50];
namsinh = 1980;
diemtb = 0;
} SinhVien(char*,char*,int,fl oat);
… };
Stack( int max = 10) {
soluong = max;
vitri = 0;
ds = new
float [soluong];
} Stack( float * d, int m,
int n);
… };
Cấp vùng nhớ cho con trỏ
Trang 2• N ếu không có ñịnh nghĩa hàm xây dựng:
– Mặc nhiên sẽ tự ñộng có 1 hàm xây dựng không tham số.
– Chỉ có 1 cách khởi tạo ñối tượng theo dạng không tham số.
class Diem {
int x, y;
public :
void main() { Diem a;
Diem *pa = new Diem();
5
public :
void InDiem();
void NhapDiem();
void GanGiaTri( int ,
int );
int GiaTriX();
int GiaTriY();
…
};
// ðị nh ngh ĩ a các hàm
thành viên
…
…
a
x y
1000H
Diem *pa = new Diem();
Diem ds1[10];
Diem *ds2 = new
Diem[20];
… }
Không có giá trị ñầu nên dễ gây ra
hiệu ứng phụ
• N ếu có ñị nh ngh ĩ a ít nhất 1 hàm xây dựng:
– Có bao nhiêu hàm xây dựng sẽ có bấy nhiêu cách khởi tạo ñối tượng theo dạng ñã ñịnh nghĩa.
void main() { PhanSo a;
PhanSo b(3);
void main() { Stack a;
Stack b(5);
6
PhanSo b(3);
PhanSo c(2,5);
PhanSo d[3];
PhanSo *pa = new PhanSo;
PhanSo *pa1 = new PhanSo();
PhanSo *pa2 = new PhanSo[5];
PhanSo *pb = new PhanSo(3);
PhanSo *pc = new
PhanSo(2,5);
… }
Stack b(5);
Stack c[5];
Stack *pa = new Stack(); Stack *pb = new Stack(40); Stack *pc = new Stack[40]; float data[40];
for ( int i=0;i<10;i++) data[i]=i;
Stack d(data, 30, 10);
… }
• Trình t ự thực hiện:
– ðối tượng ñược tạo ra trước.
– Hàm xây dựng sẽ gọi sau trên ñối tượng.
tu mau
2 5
tu mau
PhanSo c(2,5);
7
c
c
mau
PhanSo
*pa2 = new
PhanSo[5];
tu mau
1000H
*pa2
1000H
*pa2
1000 01 01 01 01 01
0
1200 5
*ds soluong vitri
1200H
Stack
b(5);
*ds soluong vitri
…
…
…
Hàm h ủ y
Hàm h ủ y • M ục ñích: thu h ồi vùng nhớ ñã cấp cho con
trỏ là dữ liệu thành viên => delete con tr ỏ
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public :
class Stack {
float * ds;
int soluong;
int vitri;
public :
8
public : SinhVien() { strcpy(mssv,””);
hoten = new char [50];
namsinh = 1980;
diemtb = 0; }
~SinhVien() {
delete [] hoten; }
… };
Stack( int max = 10) { soluong = max;
vitri = 0;
ds = new
float [soluong];
}
~Stack() {
delete [] ds; }
… };
Trang 3• Th ứ tự thực hiện: g ọi trước khi hủy ñối tượng:
– Kết thúc 1 hàm mà trong ñó ta có khởi tạo ñối tượng.
– Thu hồi vùng nhớ cho con trỏ ñối tượng.
void HamMinhHoa() {
Stack a;
Hàm xây dựng ñược gọi Hàm hủy ñược gọi cho
Hàm h ủ y
Hàm h ủ y
9
Stack a;
Stack *pa = new Stack(8);
…
delete pa;
Stack *pb = new Stack[5];
…
delete[] pb;
pb = new Stack(20);
…
}
Hàm hủy ñược gọi cho ñối tượng mà pa ñang trỏ tới Hàm xây dựng ñược gọi 5 lần
Hàm hủy ñược gọi 5 lần
Hàm hủy ñược gọi cho a
trước khi kết thúc hàm HamMinhHoa() Hàm xây dựng ñược gọi
• T ại sao cần hàm xây dựng sao chép?
– Khởi tạo 1 ñối tượng có giá trị giống 1 ñối tượng khác – Khác với phép gán (dấu =)
• N ếu không ñị nh ngh ĩ a hàm xây dựng sao chép:
– Ngôn ngữ sẽ ự ñộng tạo ra cho ta: nội dung là gán (=) – Ngôn ngữ sẽ ự ñộng tạo ra cho ta: nội dung là gán (=) tương ứng từng thành phần.
– Không chính xác khi có dữ liệu thành viên là con trỏ.
10
*ds soluong vitri
1300 8 3
4 3.2 1.4 …
1300H
Stack a(8);
…
a
*ds 1300 8
2 con trỏ sẽ trỏ
Stack b(a);
*ds soluong vitri
8 3
b
cùng 1 ñịa chỉ nếu không ñịnh nghĩa hàm xây dựng sao chép
• Cú pháp: <Tên l ớ p> (const <Tên l ớ p> & )
{ N ộ i dung hàm }
VD: Diem(const Diem& d) { … } Stack(const Stack& s) { … } SinhVien(const SinhVien& sv) { … }
SinhVien(const SinhVien& sv) { … }
• N ội dung:
– Gán tương ứng các thành phần dữ liệu (không là con trỏ) – Cấp vùng nhớ và sao chép nội dung vùng nhớ từ ñối tượng cho trước.
VD: Diem(const Diem& d) { x=d.x; y=d.y; } PhanSo(const PhanSo& p) { tu=p.tu;
Trang 4• Ví d ụ :
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public :
*hoten namsinh diemtb
1240 1974 8.14
1240H
SinhVien nva; …
9
1 2 0 8 9 1 \0 mssv[]
13
public :
…
SinhVien( const SinhVien & s){
strcpy(mssv, s.mssv);
hoten = new char[50];
strcpy(hoten, s.hoten);
namsinh = s.namsinh;
diemtb = s.diemtb;
}
…
};
N g u y e n … …
1240H
2760 1974 8.14
9
1 2 0 8 9 1 \0
N g u y e n … …
SinhVien x(nva);
*hoten namsinh diemtb mssv[]
• Ví d ụ :
class Stack {
float * ds;
int soluong;
int vitri;
public :
…
*ds soluong vitri
1300 8 3
4 3.2 1.4 … …
1300H
a Stack a(8); …
14
… Stack( const Stack & s) { soluong = s.soluong;
vitri = s.vitri;
ds = new float [soluong];
for ( int i=0; i<vitri; i++) ds[i]=s.ds[i];
}
… };
a
Stack b(a);
1570 8 3
4 3.2 1.4 … …
1570H
b
copy
*ds soluong vitri
• S ử dụng trong các trường hợp:
– ðối tượng ñược truy ề n theo giá tr ị của ñối số 1 hàm.
– Tr ị tr ả v ề của hàm là 1 ñối tượng.
– Tạo ra 1 ñối tượng có giá tr ị gi ố ng 1 ñối tượng cho trước.
class A {
int x;
A HamThu( x) {
15
int x;
public :
A () { x=0; }
A const A& a) {
x=a.x;
}
void Hien() {
cout <<“x=“<<x;
}
};
A y(x);
return y;
}
void main() {
A a,b;
b = HamThu(a);
A c = b;
A *d = new A(c);
}
Có bao nhiêu hàm xây dựng sao chép ñược gọi?
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
• Gi ới thiệu:
– Thuộc tính của 1 lớp có thể có kiểu bất kỳ.
– Thuộc tính của 1 lớp có thể là ñối tượng của 1 lớp khác.
Sử dụng lại 1 lớp, nhưngkhông không phải phải là là thừa thừa kế kế
class Diem { class DuongTron {
16
class Diem { int x, y;
public : Diem();
Diem(int , int);
void Nhap();
void Hien();
void DoiDiem(int,int);
int GiaTriX();
int GiaTriY();
};
class DuongTron { Diem tam;
int bankinh;
public:
DuongTron();
void Ve();
void Nhap();
void DoiDTron(int,int);
float ChuVi();
float DienTich();
};
Trang 5• Cách truy xu ất:
– Khi truy xuấ ñến thuộc tính là ñối tượng, phải thông qua
tên c ủ a thu ộ c tính.
– Lưu ý ñến thu ộ c tính truy c ậ p (public, private, …) của
thành phần dữ liệu và hàm thành viên của lớp tạo ra ñối
tượng ñó ñể truy xuất hợp lý.
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
tượng ñó ñể truy xuất hợp lý.
Void DuongTron::Ve() {
cout <<“Tam : “;
tam.Hien() ;
cout <<endl;
cout <<“Ban kinh : “
<<bankinh<<endl;
}
Void DuongTron::Nhap() {
7
10 20
tam bankinh
x y
DuongTron a;
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
18
Void DuongTron::Nhap() {
cout <<“Nhap tam : “
<<endl;
tam.Nhap ();
cout <<“Nhap ban kinh : “; cin>>bankinh;
}
void DuongTron::
DoiDTron( int dx, int dy) {
tam.DoiDiem (dx, dy);
}
• Hàm xây d ựng:
– Phải kh ở i t ạ o cho thu ộ c tính là ñố i t ượ ng theo dạng
hàm xây dựng của lớp ñó.
DuongTron() : tam()
{ bankinh=0; }
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
19
DuongTron(Diem d, int bk) : tam(d)
{ bankinh=bk; }
DuongTron(int x, int y, int bk) : tam(x,y)
{ bankinh=bk; }
DuongTron(const DuongTron& d): tam(d.tam)
{bankinh=d.bankinh;}
• Hàm xây d ựng:
Nếu có nhiều thuộc tính là ñối tượng, khởi tạo các ñối tượng này liên tiếp nhau thông qua dấu phẩy ( , ).
Cú pháp này cho phép áp dụng cả với thuộc tính thường.
Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng Thu ộ c tính c ủ a 1 l ớ p là ñố i t ượ ng
20
Duongtron() : tam(), bankinh(0) {}
Duongtron(Diem d, int bk) : tam(d), bankinh(bk) {}