160 likes | 386 Views
Chương 4 :. 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 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. Hàm xây dựng. 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.
E N D
Chương 4: 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 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 Nguyễn Công Huy – Khoa CNTT&TT
Hàm xây dựng • 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. classDiem { int x, y; public: Diem(int a) { x = y = a; } Diem(int h, int t) { x = h; y=t; } …. }; classPhanSo { 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; } …. }; Nguyễn Công Huy – Khoa CNTT&TT
Hàm xây dựng • Ví dụ: classSinhVien { 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 = newfloat[soluong]; } Stack(float* d, int m, int n); … }; Cấp vùng nhớ cho con trỏ Nguyễn Công Huy – Khoa CNTT&TT
1000H x … y … a 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 đối tượng theo dạng không tham số. classDiem { 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 … voidmain() { 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ụ Nguyễn Công Huy – Khoa CNTT&TT
Hàm xây dựng • 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. voidmain() { 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); … } voidmain() { 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); … } Nguyễn Công Huy – Khoa CNTT&TT
0 0 0 0 2 0 1 1 5 1 1 1 PhanSo c(2,5); tu tu mau mau 1000H 1000H c c tu tu PhanSo *pa2 = new PhanSo[5]; 1000 1000 mau mau *pa2 *pa2 1200H … 1200 *ds *ds Stack b(5); … 5 soluong soluong … 0 vitri vitri Hàm xây dựng • 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. Nguyễn Công Huy – Khoa CNTT&TT
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ỏ. classSinhVien { char mssv[8]; char* hoten; int namsinh; float diemtb; public: SinhVien() { strcpy(mssv,””); hoten = newchar[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 = newfloat[soluong]; } ~Stack() { delete[] ds; } … }; Nguyễn Công Huy – Khoa CNTT&TT
Hàm hủy • 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. voidHamMinhHoa() { 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 đ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 xây dựng được gọi Hàm hủy được gọi cho a trước khi kết thúc hàm HamMinhHoa() Nguyễn Công Huy – Khoa CNTT&TT
1300 1300 *ds *ds 8 8 soluong soluong 3 3 vitri vitri Hàm xây dựng sao chép • 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ếukhông định nghĩa hàm xây dựng sao chép: • Ngôn ngữ sẽ tự độ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ỏ. 1300H Stack a(8); … 4 3.2 1.4 … … … … … 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 a Stack b(a); b Nguyễn Công Huy – Khoa CNTT&TT
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) { … } • 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; mau=p.mau; } Nguyễn Công Huy – Khoa CNTT&TT
Hàm xây dựng sao chép • Ví dụ: SinhVien nva; … classSinhVien { char mssv[8]; char* hoten; int namsinh; float diemtb; public: … SinhVien(constSinhVien& s) { strcpy(mssv, s.mssv); hoten = new char[50]; strcpy(hoten, s.hoten); namsinh = s.namsinh; diemtb = s.diemtb; } … }; 1 9 2 0 8 9 1 \0 mssv[] 1240 *hoten namsinh 1974 diemtb 8.14 1240H N g u y e n … … copy 2760H N g u y e n … … 1 9 2 0 8 9 1 \0 mssv[] 2760 *hoten namsinh 1974 diemtb 8.14 SinhVien x(nva); Nguyễn Công Huy – Khoa CNTT&TT
1570 1300 *ds *ds 8 8 soluong soluong 3 3 vitri vitri Hàm xây dựng sao chép • Ví dụ: class Stack { float *ds; int soluong; int vitri; public: … Stack(constStack& s) { soluong = s.soluong; vitri = s.vitri; ds = newfloat[soluong]; for(int i=0; i<vitri; i++) ds[i]=s.ds[i]; } … }; Stack a(8); … 1300H 4 3.2 1.4 … … … … … a copy 4 3.2 1.4 … … … … … 1570H b Stack b(a); Nguyễn Công Huy – Khoa CNTT&TT
Hà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. classA { int x; public: A() { x=0; } A (constA& a) { x=a.x; } void Hien() { cout<<“x=“<<x; } }; AHamThu(A x) { A y(x); return y; } voidmain() { 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? Nguyễn Công Huy – Khoa CNTT&TT
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ưng không phải là thừa kế classDiem { int x, y; public : Diem(); Diem(int , int); void Nhap(); void Hien(); void DoiDiem(int,int); int GiaTriX(); int GiaTriY(); }; classDuongTron { Diem tam; int bankinh; public: DuongTron(); ... void Ve(); void Nhap(); void DoiDTron(int,int); float ChuVi(); float DienTich(); }; Nguyễn Công Huy – Khoa CNTT&TT
10 x tam y 20 bankinh 7 DuongTron a; Thuộc tính của 1 lớp là đối tượng • Cách truy xuất: • Khi truy xuất đế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ý. voidDuongTron :: 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; } voidDuongTron :: DoiDTron(int dx, int dy) { tam.DoiDiem(dx, dy); } Nguyễn Công Huy – Khoa CNTT&TT
Thuộc tính của 1 lớp là đối tượng • 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; } DuongTron(Diem d, int bk) : tam(d) { bankinh=bk; } DuongTron(int x, int y, int bk) : tam(x,y) { bankinh=bk; } DuongTron(constDuongTron& d):tam(d.tam) {bankinh=d.bankinh;} • 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. Duongtron(): tam(), bankinh(0) {} Duongtron(Diem d, int bk) : tam(d), bankinh(bk) {} Nguyễn Công Huy – Khoa CNTT&TT