Các lp
Lp là mt phương thc logic để t chc d liu và các hàm trong cùng mt cu
trúc. Chúng được khai báo s dng t khoá class, t này có chc năng tương t
vi t khoá ca C struct nhưng có kh năng gp thêm các hàm thành viên.
Dng thc ca nó như sau:
class class_name {
permission_label_1:
member1;
permission_label_2:
member2;
...
} object_name;
trong đó class_name là tên ca lp ( kiu người dùng t định nghĩa) và trường
mc định object_name là mt hay mt vài tên đối tượng hp l. Phn thân ca
khai báo cha các thành viên ca lp, đó có th là d liu hay các hàm và có th
là các nhãn cho phép ( permission labels) là mt trong nhng t khoá sau
đây: private:, public: hoc protected:.
Các thành viên private ca mt lp ch có th được truy xut t các
thành viên khác ca lp hoc t các lp "bn bè".
Các thành viên protected có th được truy xut t các thành viên trong
cùng mt lp và các lp bn bè, thêm vào đó là t các thành viên ca các
lp tha kế
Cui cùng, các thành viên public có th được truy xut t bt kì ch nào
mà lp nhìn thy.
Nếu chúng ta khai báo các thành viên ca mt lp trước khi thêm vào các nhãn
cho phép thì các thành viên đó đưc coi là private.
Ví d:
class CRectangle {
int x, y;
public:
void set_values (int,int);
int area (void);
} rect;
Khai báo lp CRectangle và mt đối tượng có tên rect có kiu là lp
CRectangle. Lp này cha bn thành viên: hai viến có kiu int (xy) trong
phn private (vì private là s cho phép mc định) và hai hàm trong phn
public: set_values()area(), đây chúng ta ch mi khai báo mu.
Hãy chú ý s khác bit gia tên lp và tên đối đối tượng: Trong ví d trước,
CRectangle là tên lp còn rect là tên mt đối tượng có kiu CRectangle.
Trong các phn tiếp theo ca chương trình chúng ta có th truy xut đến các thành
viên public ca đối tượng rect nhưđối vi các hàm hay các biến thông thường
bng cách đặt tên ca đối tượng ri sau đó là mt du chm và tên thành viên ca
lp (như chúng ta đã làm vi các cu trúc ca C). Ví d:
rect.set_value (3,4);
myarea = rect.area();
nhưng chúng ta không có kh năng truy xut đến x hay y vì chúng là các thành
viên private ca lp và chúng ch có th được truy xut t các thành viên ca cùng
mt lp. Bi ri? Đây là ví d đầy đủ v lp CRectangle:
// classes example
#include <iostream.h>
class CRectangle {
int x, y;
public:
void set_values
(int,int);
int area (void)
{return (x*y);}
};
void
CRectangle::set_values
(int a, int b) {
x = a;
y = b;
}
int main () {
CRectangle rect;
rect.set_values (3,4);
cout << "area: " <<
area: 12
rect.area();
}
Mt điu mi trong đon mã này là toán t phm vi :: được dùng trong khai báo
set_values(). Nó được s dng để khai báo bên ngoài các thành viên ca
mt lp. Chú ý rng chúng ta đã định nghĩa đầy đủ hàm area() ngay bên trong
lp trong khi hàm set_values() mi ch được khai báo mu còn định nghĩa
ca nó nm ngoài lp. Trong phn khai báo ngoài này chúng ta bt buc phi
dùng toán t ::.
S khác bit duy nht gia vic khai báo đầy đủ mt hàm bên trong lp và vic ch
khai báo mu là trong trường hp th nht hàm s được t động coi là inline bi
trình dch, còn trong trường hp th hai nó s là mt hàm thành viên bình thường.
Lý do khiến chúng ta khai báo xy là các thành viên private vì chúng ta đã
định nghĩa mt hàm để thâótc vi chúng (set_values()) và không có lý do gì
để truy nhp trc tiếp đến các biến này. Có l trong ví d rt đơn gin này bn
không thy đưc mt tin ích ln khi bo v hai biến này nhưng trong các d án
ln hơn nó có th là rt quan trng khi đảm bo được rng các giá tr đó không b
thay đổi mt cách không mong mun.
Mt ích li na ca lp là chúng ta có th khai báo mt vài đối tượng khác nhau t
nó. Ví d, tiếp sau đây là ví d trước v lp CRectangle, tôi ch thêm phn khai
báo thêm đối tượng rectb.
// class example
#include <iostream.h>
class CRectangle {
int x, y;
public:
void set_values
(int,int);
int area (void)
{return (x*y);}
};
void
CRectangle::set_values
(int a, int b) {
x = a;
rect area: 12
rectb area: 30
y = b;
}
int main () {
CRectangle rect, rectb;
rect.set_values (3,4);
rectb.set_values (5,6);
cout << "rect area: " <<
rect.area() << endl;
cout << "rectb area: "
<< rectb.area() << endl;
}
Chú ý rng li gi đến rect.area() không cho cùng kết qu vi
rectb.area() vì mi đối tượng ca lp CRectangle có các biến và các hàm
ca riêng nó
Trên đây là nhng khái nim cơ bn v đối tượng và lp trình hướng đối tượng.
Trong đối tượng các d liu và các hàm là các thuc tính thay vì trước đây đối
tượng là các tham s ca hàm trong lp trình cu trúc. Trong bài này các phn tiếp
sau chúng ta s nói đến nhng li ích ca phương thc này.
Constructors và destructors
Nói chung các đối tượng cn phi khi to các biến hoc cp phát b nh động
trong quá trình to ra chúng để có th hot động tt và tránh được vic tr v các
giá tr không mong mun. Ví d, điu gì s xy ra nếu chúng ta gi hàm area()
trước khi gi hàm set_values?Có l kết qu s là mt giá tr không xác định vì
các thành viên xy chưa được gán mt giá tr c th nào.
Để tránh điu này, mt lp cn có mt hàm đặc bit: mt constructor, hàm này có
th được khai báo bng cách đặt tên trùng vi tên ca lp. Nó s được gi t động
khi mt khai báo mt đối tượng mi hoc cp phát mt đối tượng có kiu là lp
đó. Chúng ta thêm mt constructor vào lp CRectangle:
// classes example
#include <iostream.h>
class CRectangle {
int width, height;
public:
rect area: 12
rectb area: 30
CRectangle (int,int);
int area (void)
{return (width*height);}
};
CRectangle::CRectangle
(int a, int b) {
width = a;
height = b;
}
int main () {
CRectangle rect (3,4);
CRectangle rectb (5,6);
cout << "rect area: " <<
rect.area() << endl;
cout << "rectb area: "
<< rectb.area() << endl;
}
Như bn có th thy, kết qu ca ví d này ging vi ví d trước. Trong trường
hp này chúng ta ch thay thế hàm set_values bng mt hàm constructor.
Hãy chú ý cách mà các tham s được truyn cho constructor khi mt đối tượng
được to ra:
CRectangle rect (3,4);
CRectangle rectb (5,6);
Bn có th thy rng constructor không có giá tr tr v, ngay c kiu void cũng
không. Điu này luôn luôn phi như vy.
Destructor làm các chc năng ngược li. Nó s được t động gi khi mt đối
tượng được gii phóng khi b nh hay phm vi tn ti ca nó đã kết thúc (ví d
như nếu nó được định nghĩa là mt đối tượng cc b bên trong mt hàm và khi
hàm đó kết thúc thì phm vi tn ti ca nó cũng hết) hoc nó là mt đối tượng đối
tượng được cp phát động và s gii phóng bi toán t delete.
Destructor phi có cùng tên vi tên lp vi du (~) đằng trước và nó không được
tr v giá tr nào.