HÀM XÂY DỰNG, HÀM HỦY VÀ ViỆC KHỞI TẠO ĐỐI TƯỢNG... Hàm xây dựng 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
Trang 1HÀM XÂY DỰNG, HÀM HỦY VÀ ViỆC KHỞI TẠO ĐỐI TƯỢNG
Trang 2Hàm xây dựng
class Diem {
int x, y;
public:
Diem(int a) { x = y = a; } Diem(int h, int t) { x = h; y=t; }
…
};
class PhanSo {
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; }
…
};
Trang 3Hàm xây dựng
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public:
SinhVien() {
strcpy(mssv,””);
hoten = new char[50];
namsinh = 1980;
diemtb = 0;
}
SinhVien(char*,char*,int,float);
…
};
class Stack { float *ds;
int soluong;
int vitri;
public: 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 4Hàm xây dựng
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 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
void main() { Diem a;
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ụ
Trang 5Hàm xây dựng
Nếu có định nghĩa ít nhất 1 hàm xây dựng:
tạo đối tượng theo dạng đã định nghĩa.
void main() {
PhanSo a;
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);
…
void main() { Stack a;
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); … }
Trang 6Hàm xây dựng
c
tu mau
2 5
c
tu mau
PhanSo c(2,5);
PhanSo *pa2 =
mau
1000H
*pa2
mau
1000H
*pa2
1000
0 1
0 1
0 1
0 1
0 1
0
1200 5
*ds soluong vitri
1200H
Stack b(5);
*ds soluong vitri
…
…
…
Trang 7Hàm hủy
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public:
SinhVien() {
strcpy(mssv,””);
hoten = new char[50];
namsinh = 1980;
diemtb = 0;
}
~SinhVien() { delete[] hoten; }
…
};
class Stack { float *ds;
int soluong;
int vitri;
public: Stack(int max = 10) { soluong = max;
vitri = 0;
ds = new float[soluong]; }
~Stack() { delete[] ds; } …
};
Trang 8Hàm hủy
void HamMinhHoa() { Stack a;
Stack *pa = new Stack(8);
… delete pa;
Stack *pb = new Stack[5];
… delete[] pb;
pb = new Stack(20);
… }
Hàm xây dựng được gọi
Hàm hủy được gọi cho đối tượng mà pa pa đang trỏ tới
Hàm xây dựng được gọi 5 lần 5 lần
Hàm hủy được gọi 5 lần 5 lần
Hàm hủy được gọi cho a a trước khi kết thúc hàm HamMinhHoa() Hàm xây dựng được gọi
Trang 9Hàm xây dựng sao chép
Nếu không định nghĩa hàm xây dựng sao chép:
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ỏ.
*ds soluong vitri
1300 8 3
4 3.2 1.4 … … … … …
1300H
Stack a(8);
…
a Stack b(a);
*ds soluong vitri
1300 8 3
2 con trỏ sẽ trỏ cùng 1 địa chỉ nếu không định nghĩa hàm xây dựng sao chép
Trang 10Hàm xây dựng sao chép
<Tên lớp> (const const <Tên lớp> & ) { Nội dung hàm }
VD:
Diem(const Diem& d) { … } Stack(const Stack& s) { … } SinhVien(const SinhVien& sv) { … }
tượng cho trước.
VD:
Diem(const Diem& d) { x=d.x; y=d.y; } PhanSo(const PhanSo& p) { tu=p.tu; mau=p.mau; }
Trang 11Hàm xây dựng sao chép
class SinhVien {
char mssv[8];
char* hoten;
int namsinh;
float diemtb;
public :
…
SinhVien( const SinhVien & s) {
strcpy(mssv, s.mssv);
hoten = new char[50];
strcpy(hoten, s.hoten);
namsinh = s.namsinh;
diemtb = s.diemtb;
}
…
*hoten namsinh diemtb
1240 1974 8.14
N g u y e n … …
1240H
SinhVien nva; … 9
1 2 0 8 9 1 \0
mssv[]
*hoten namsinh diemtb
2760 1974 8.14
9
1 2 0 8 9 1 \0
mssv[]
N g u y e n … …
Trang 12Hàm xây dựng sao chép
class Stack {
float *ds;
int soluong;
int vitri;
public:
…
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];
}
…
};
*ds soluong vitri
1300 8 3
4 3.2 1.4 … … … … …
1300H
a Stack a(8); …
Stack b(a);
*ds soluong vitri
1570 8 3
4 3.2 1.4 … … … … …
1570H
b
copy
Trang 13Hàm xây dựng sao chép
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.
int x;
A A() { x=0; }
A A ( const A& A& a) {
x=a.x;
}
void Hien() {
cout <<“x=“<<x;
}
};
A A y(x);
return y;
}
A a,b;
b = HamThu(a);
A c = b;
A *d = new A(c);
}
Hàm xây dựng sao chép được gọi bao nhiêu lần?
Trang 14Thuộc tính của 1 lớp là đối tượng
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 15Thuộc tính của 1 lớp là đối tượng
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ý.
void DuongTron :: Ve() {
cout<<“Tam : “; tam.Hien(); cout<<endl; cout<<“Ban kinh : “<<bankinh<<endl;
}
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);
7
10 20
tam
bankinh
x y
DuongTron a;
Trang 16Thuộc tính của 1 lớp là đối tượng
xây dựng của lớp đó.
thường.
DuongTron() : tam() { bankinh=0; }
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;}
Duongtron(): tam(), bankinh(0) {}
Duongtron(Diem d, int bk) : tam(d), bankinh(bk) {}