CHƯƠNG 11: ĐỐI TƯỢNG VÀ LỚP
• Nội dung
Đối tượng
Lớp
Con trỏ this
Hàm thiết lập
Hàm hủy bỏ
Hàm thiết lập sao chép
Các thành phần tĩnh
Hàm bạn và lớp bạn
Đối tượng
• Đối tượng là một khái niệm trong lập trình hướng đối tượng biểu thị sự liên kết
giữa dữ liệu và các thủ tục (gọi là phương thức) thao tác trên dữ liệu
• ĐỐI TƯỢNG = DỮ LIỆU + PHƯƠNG THỨC
Lớp
Lớp là một mô tả nhóm các đối tượng có cùng bản chất, ngược lại mỗi một đối
tượng là một biểu hiện cụ thể cho những mô tả trừu tượng đó.
• khai báo lớp
• class <tên lớp>
• {
• private:
• <khai báo các thành phần riêng trong từng đối tượng>
• public:
• <khai báo các thành phần công cộng trong từng đối tượng>
• };
• <định nghĩa các hàm thành phần chưa được định nghĩa bên trong khai báo lớp>
Các thành phần của lớp có thể là thành phần dữ liệu (thuộc tính) hoặc hàm thành
phần (phương thức).
Thành phần dữ liệu được khai báo giống như khai báo biến
Hàm thành phần được khai báo giống như khai báo hàm trong C. Có hai
cách định nghĩa một hàm thành phần: định nghĩa trong lớp và ngoài lớp.
là đối tượng thực hiện lời gọi hàm. Như vậy các thành phần dữ liệu viết
trong các hàm thành phần được hiểu là thuộc đối tượng dùng làm tham số
ngầm định trong lời gọi hàm.
Con trỏ this
• C++ sử dụng con trỏ đặc biệt this trong các hàm thành phần. Con trỏ này
luôn trỏ tới đối tượng dùng làm tham số ngầm định trong lời gọi hàm thành
phần.
• Ví dụ 2: Các hàm thành phần Nhap() và Xuat() có thể viết theo cách khác
như sau
• void Diem::Nhap()
• {
• cout <<“Nhap toa do:”;
• cin >> this->x >> this->y;
• }
• void Diem::Xuat()
• {
• cout << this->x <<“,” << this->y <<“\n”;
• }
Hàm thiết lập
Hàm thiết lập là một hàm đặc biệt được gọi tự động mỗi khi có một đối
tượng được khai báo.
Chức năng của hàm thiết lập là để khởi tạo giá trị cho các thành phần dữ
liệu hoặc xin cấp phát vùng nhớ cho các thành phần dữ liệu động.
Hàm thiết lập được khai báo giống như một hàm thành phần với tên trùng
tên với lớp, không có giá trị trả về và không cần khai báo void.
Có thể có nhiều hàm thiết lập trong cùng một lớp (chồng hàm thiết lập).
Khi một lớp có nhiều hàm thiết lập, việc tạo ra các đối tượng phải kèm theo
các tham số phù hợp với một trong các hàm thiết lập đã khai bào.
Khi người sử dụng không khai báo tường minh bất kỳ một hàm thiết lập
nào cho lớp thì trình biên dịch tự động phát sinh cho lớp một hàm thiết lập
• void main()
• {
• Diem a; //Gọi hàm thiết lập không đối số
• a.Xuat();
• Diem b(2); //Gọi hàm thiết lập một đối số
• b.Xuat();
• Diem c(2, -4); //Gọi hàm thiết lập hai đối số
• c.Xuat();
• }
• Ví dụ 4:
• Class Diem
• {
• private:
• int x, y;
• public:
• . . .
• Diem(int xx = 0, int yy = 0); /*Khai báo hàm thiết lập hai đối số có
giá trị ngầm định*/
• };
• Diem::Diem(int xx, int yy)
• { cout << “Goi ham thiet lap hai doi so\n”;
• x = xx; y = yy;
• }
• void main()
• {
• // giống ví dụ 3
• }
Hàm hủy bỏ
Hàm hủy bỏ là một hàm đặc biệt được gọi tự động khi đối tượng tương ứng
bị xóa khỏi bộ nhớ.
• {
• Test u(2*r) //Gọi hàm thiết lập 1 đối số
• }
• //Hàm chính
• void main()
• {
• Test a(1); //Gọi tới hàm thiết lập một đối số
for(int i = 1; i <= 2; i++)
• fct(i); //gọi hàm tự do fct()
• }
Sự cần thiết của hàm thiết lập và hàm hủy bỏ
• Trên thực tế với các lớp không có thành phần dữ liệu động chỉ cần sử dụng
hàm thiết lập và hủy bỏ ngầm định là đủ. Hàm thiết lập và hủy bỏ do người
lập trình tạo ra rất cần thiết khi các lớp có chứa thành phần dữ liệu động.
Khi tạo đối tượng hàm thiết lập xin cấp phát một bộ nhớ động, do đó hàm
hủy bỏ sẽ giải phóng vùng nhớ động đã được cấp phát trước đó.
• Ví dụ 6:
• class Vector
• {
• private:
• int n; //số chiều
• float *p; //con trỏ tới vùng nhớ tọa độ
• public:
• Vector(); Vector(int nn); ~vector();
• void Nhap(); void Xuat();
• };
• //Định nghĩa các hàm thành phần
• Vector::vector()
• { cout << “Goi ham thiet lap khong doi\n”;
• cout << “Nhap so chieu:”; cin >> n;
• a.Nhap();
• a.Xuat();
• Vector b(3); //Gọi hàm thiết lập một đối
• b.Nhap();
• b.Xuat();
• }
• Chú ý: Nếu chỉ sử dụng hàm thiết lập mặc định thì đối tượng a được tạo ra
bởi các lệnh khai báo sẽ chưa có bộ nhớ để chứa các tọa độ. Như vậy đối
tượng chưa hoàn chỉnh và chưa dùng được.
Hàm thiết lập sao chép
Hàm thiết lập được gọi khi khai báo và khởi tạo nội dung một đối tượng
thông qua một đối tượng khác gọi là hàm thiết lập sao chép. Nhiệm vụ của
hàm thiết lập sao chép là tạo ra một đối tượng giống hệt một đối tượng đã
có trước đó.
Dạng khai bao hàm thiết lập sao chép:
<Tên lớp>(<Tên lớp> & <Tên đối số>);
Ngoài tình huống trên đây, còn có hai tình huống cần dùng hàm thiết lập
sao chép: truyền đối tượng cho hàm bằng tham trị hoặc hàm trả về một đối
tượng giống hệt một đối tượng cùng lớp đã có trước đó.
Giống như hàm thiết lập ngầm định, nếu không được khai báo tường minh,
sẽ có một hàm thiết lập sao chép ngầm định do chương trình dịch cung cấp.
Hàm này chỉ thực hiện thao tác tối thiểu: sao chép giá trị của các thành
phần dữ liệu trong đối tượng nguồn cho các thành phần dữ liệu tương ứng
trong đối tượng đích.
• Ví dụ 7:
• class Diem
• {
• private:
• . . .
• public:
• private:
• . . .
• public:
• . . .
• Vector(Vector &u); //Hàm thiết lập sao chép
• int GetN() { return n;}
• float Nhan(Vector u); //Tích vô hướng hai vector
• };
• //Định nghĩa các hàm thành phần
• Vector::Vector(Vector &u)
• { cout << “Goi ham thiet lap sao chep của lop Vector\n”;
• n = u.n;
• p = new int [n]; //Cấp phát vnđ bằng kích thước có trong đt nguồn
• //Gán nội dung vnđ trong đt nguồn sang đt đích
• for(int i =0; i < n; i++)
• p[i] = u.p[i];
• }
• float Vector::Nhan(Vector u)
• { float res = 0;
• for(i = 0; i < n; i++)
• res += p[i] * u.p[i];
• return res;
• }
• //Hàm chính
• void main()
• { . . .
• Vector c = a; //Gọi hàm thiết lập sao chép
• c.Xuat();
• if(b.GetN() == c.GetN()) {
• float kq = b.Nhan(c); //Gọi hàm thiết lập sao chép
• //Khai báo hàm tự do Nhan() là bạn của lớp vector
• friend Vector Nhan(MaTran u, Vector v);
• };
• class MaTran
• { . . .
• public:
• . . .
• //Khai báo hàm tự do Nhan() là bạn của lớp MaTran
• friend Vector Nhan(MaTran u, vector v);
• };
• Vector Nhan(Matran u, Vector v); //Khai báo nguyên mẫu
• //Định nghĩa hàm tự do Nhan()
• Vector Nhan(MaTran u, Vector v)
• { Vector res(u.m);
• for(int i = 0; i < u.m; i++) {
• res.p[i] = 0;
• for(int j = 0; j < v.n; j++)
• res.p[i] += u.p[i][j] * v.p[j];
• }
• return res;
• }
• void main()
• { Vector a(3); a.Xuat();
• Matran b(2, 3); b.Xuat();
• if(b.GetN() == a.GetN()) {
• Vector c = Nhan(b, a); c.Xuat();
• }
• else cout << “b * a khong thuc hien duoc\n”;
• }
Hàm thiết lập và đối tượng thành phần