Chương 3 Lớp và đối tượng
Ầ
TR N MINH THÁI Email: minhthai@itc.edu.vn Website: www.minhthai.edu.vn
Cập nhật: 08 tháng 02 năm 2015
Nội dung
#2
1. Khái niệm lớp và đối tượng
2. Toán tử gán
3. Phương thức thiết lập (constructor)
4. Phương thức huỷ (destructor)
5. Con trỏ this
6.
Lớp template
Lớp đối tượng là gì? (1/2)
#3
• Lớp là khái niệm trung tâm của OOP, là sự mở rộng của khái
niệm cấu trúc (struct)
• Ngoài thành phần dữ liệu (như cấu trúc), lớp còn chứa các thành phần hàm, còn gọi là phương thức (method) hay hàm thành viên (member function)
Lớp đối tượng là gì? (2/2)
#4
• Lớp được xem như một kiểu dữ liệu (kiểu đối tượng)
• Lớp giúp lập trình viên:
•
Trừu tượng hóa dữ liệu
• Đóng gói
•
và ẩn thông tin
Khai báo lớp (1/2)
#5
• Cú pháp
class class_name
{
: member_list
};
Với member_list là đặc tả các thành viên
Theo quy ước, tên lớp bắt đầu bởi ký tự C
Khai báo lớp (2/2)
#6
• Thành viên của lớp gồm
•
Thành viên dữ liệu (data member) (cid:0)
thuộc tính
• Hàm thành viên (member function) (cid:0)
phương thức
ớ
ờ
class CTime //L p th i gian {
private:
Thuộc tính
int hour, minute, second;
public:
void SetTime(int h, int m, int s); void Print();
Phương thức
};
Khai báo lớp: thuộc tính (1/5)
#7
• Là dữ liệu khai báo trong lớp
• Cú pháp giống như khai báo biến
• Có thể là một đối tượng nhưng phải khác đối tượng của lớp
đang định nghĩa (con trỏ hay tham chiếu: OK)
• Không thể vừa khai báo, vừa khởi tạo
Khai báo lớp: thuộc tính (2/5)
#8
ớ
ờ
class CTime //L p th i gian {
private:
int hour = 1; // Error int minute, second;
public:
void SetTime(int h, int m, int s); void Print();
};
Khai báo lớp: phương thức (3/5)
#9
• Hàm khai báo trong lớp (còn gọi là giao diện)
• Có thể truy cập các thành viên dữ liệu và hàm thành viên khác
• Cài đặt trong lớp hàm inline
Khai báo lớp: phương thức (4/5)
#10
• Cú pháp
class_name
::
method_name
type_name ( parameter_list )
{
…
} • Hàm inline (cid:0)
thêm từ khóa inline
Khai báo lớp: cài đặt phương thức (5/5)
#11
class CMyTime {
private:
int hour, minute, second;
public:
void SetTime(int h, int m, int s); void Print() {
cout< minute<<":"< } };
void CMyTime::SetTime(int h, int m, int s)
{ hour = (h>=0 && h<24) ? h:0;
minute = (m>=0 && m<60) ? m:0;
second = (s>=0 && s<60) ? s:0; } #12 • Xác định phạm vi của các thành viên của lớp có thể được sử dụng trực tiếp từ bên ngoài phạm vi lớp hay không • Các thuộc tính: private, protected, public #13 • private (mặc định) Chỉ được truy xuất từ bên trong lớp • protected Chỉ được truy xuất từ bên trong lớp hoặc lớp dẫn xuất của nó • public (mặc định đối với thành viên của struct) Có thể được truy xuất từ bên ngoài lớp #14 class CMyClass
{ private: int x; public: !!! Các phương thức tiện
ích chỉ được dùng bởi
các phương thức khác
trong cùng lớp nên được
khai báo private int y;
void Print()
{ cout << x << "," << y << endl; } };
void f()
{ CMyClass m;
cout< //OK } #15 • Tạo đối tượng Sử dụng lớp giống như dùng struct, khai báo một biến lớp
(tạo đối tượng) như khai báo biến struct • Khai báo con trỏ, tham chiếu tới lớp • Có thể khai báo con trỏ/ tham chiếu đến một đối tượng thuộc cùng lớp (truy cập gián tiếp) • Con trỏ/ tham chiếu không là instance của lớp #16 CMyTime t1; CMyTime &t2=t1; Gọi hàm thành viên của lớp
truyền thông điệp cho
hàm thành viên đó CMyTime *t3 = &t1; #17 • Mỗi đối tượng sẽ có một tập các dữ liệu riêng (thuộc tính) được định nghĩa trong lớp • Tuy nhiên, tập các đối tượng thuộc cùng một lớp chỉ có chung duy nhất các định nghĩa hàm (phương thức) #18 SetTime()
Print() CMyTime t1, t2;
t1.SetTime(12, 5, 5);
t2.SetTime(11,15,
15);
t1.Print();
t2.Print(); hour=12
minute=5
second=5 hour=11
minute=15
second=15 Đối tượng t1 Đối tượng t2 #19 • Dùng để gán một đối tượng
cho một đối tượng khác của
cùng một lớp • Nó được thực hiện bởi toán tử
viên thành sao
chép
(memberwise copy) CMyTime t1;
t1.SetTime(12, 5, 5);
t1.Print();
CMyTime t2;
t2 = t1; //memberwise copy
t2.Print(); #20 • Mỗi thành viên của một đối tượng này được sao chép riêng rẽ đến cùng một thành viên tương ứng của đối tượng khác • Chú ý đối với các thành viên dữ liệu chứa vùng nhớ cấp phát động hoặc con trỏ #21 • Khởi tạo các thành viên dữ liệu khi đối tượng được tạo ra • Constructor được gọi tự động mỗi khi một instance của lớp được tạo • Constructor thường được dùng để khởi tạo giá trị ban đầu hoặc cấp phát động cho các thành viên dữ liệu #22 • Constructor có cùng tên với lớp và không có giá trị trả về (kể cả void) • Phải có thuộc tính truy xuất là public • Constructor có thể có tham số (kể cả tham số mặc định) và đa năng hóa class CMyTime
#23
{ private: int hour, minute, second; public: CMyTime() //(1)
{ void CMyTime::SetTime(int h, int m, int s)
{ hour=minute=second=0; hour = (h>=0 && h<24) ? h:0;
minute = (m>=0 && m<60) ? m:0;
second = (s>=0 && s<60) ? s:0; }
CMyTime(int h, int m, int s); //(2) void SetTime(int h, int m, int s); }
void main()
{ void Print(); ọ ọ
CMyTime t1; //g i constructor (1)
t1.Print();
CMyTime t2(5,15,30);//g i constructor };
CMyTime::CMyTime(int h, int m, int s)
{ (2) SetTime(h, m, s); t2.Print(); } }
void CMyTime::Print()
{ cout< } #24 • Mặc định • Sao chép • Có tham số #25 • Không có tham số hoặc tất cả các tham số đều có giá trị mặc định • Mỗi lớp có duy nhất một constructor mặc định • Nếu không định nghĩa thì TBD sẽ tự tạo một constructor mặc
Thành viên dữ định và constructor này rỗng (không làm gì) (cid:0)
liệu sẽ có giá trị “rác” #26 class CMyTime
{ class CMyTime
{ private: private: int hour, minute, int hour, minute, second; second; public: public: CMyTime(int h=0, int m=0, int s=0); CMyTime();
… … }; }; #27 • Tạo ra 01 đối tượng mới giống với 01 đối tượng đã có • Có 01 tham số là một tham chiếu đến 01 đối tượng của cùng lớp • C++ cung cấp sẵn constructor sao chép: sao chép từng thành viên dữ liệu từ đối tượng cũ sang đối tượng mới • Nếu cần thực hiện các công việc khởi tạo khác Định nghĩa lại constructor sao chép #28 class CMyTime
{ int hour, minute, second; public: CMyTime()
CMyTime(int h, int m, int s);
CMyTime(CMyTime & t); //Copy CMyTime t1(1,20,30);
CMyTime t2(t1); //Copy constructor
CMyTime t3 = t1;//Copy constructor constructor
… };
CMyTime::CMyTime(CMyTime & t)
{ hour = t.hour;
minute = t.minute;
second = t.second; }
... #29 • Toán tử gán không tạo ra đối tượng mới: chỉ thực hiện phép gán giữa 2 đối tượng đã tồn tại • Constructor sao chép được dùng để tạo một đối tượng mới và gán
nội dung của một đối tượng đã tồn tại cho đối tượng mới vừa tạo #30 • Tự động gọi khi đối tượng bị hủy bỏ (đối tượng rời khỏi phạm vi của nó) • Đặc điểm • Tên trùng với tên lớp & theo sau bởi ký tự “~” • Không có tham số & không có trả về giá trị • Phải có thuộc tính truy xuất là public #31 • Đặc điểm • Chỉ có duy nhất một destructor trong lớp • Nếu một lớp không có định nghĩa destructor thì TBD sẽ tạo ra một destructor mặc định rỗng • Destructor thường được dùng để thực hiện việc giải phòng vùng nhớ đã được cấp phát trước khi một đối tượng bị huỷ bỏ #32 class CSimple
{ int *x; public: //Constructor //Destructor CSimple();
~CSimple();
void SetValue(int value);
int GetValue(); }; CSimple::CSimple()
{ x = new int; //Cap phat vung nho cho x } CSimple::~CSimple()
{ delete x; //Giai phong vung nho x khi doi tuong bi huy bo } #33 void CSimple::SetValue(int value)
{ *x = value; } int CSimple::GetValue()
{ return *x; } void main()
{ CSimple s;
int x;
cout<<"Nhap vao mot so:";
cin>>x;
s.SetValue(x);
cout<<"Gia tri cua so vua nhap:"< } #34 Dùng từ khóa const đối với đối tượng của một lớp để báo cho
biết đối tượng đó không thể thay đổi const CMyTime t(1,20,30);
t.SetTime(2,20,30); // Error
t.Print(); //Error??? #35 • Khi một đối tượng là hằng, một số TBD cấm hoàn toàn gọi bất
kỳ hàm thành viên nào của đối tượng đó, một số TBD thì đưa
cảnh báo (warning) • Để khắc phục, có thể khai báo các hàm thành viên là hằng (cid:0) Để đảm bảo nó không sửa đổi đối tượng #36 class CMyTime
{ private: int hour;
int minute;
int second; public: //Thiet lap hour //Thiet lap minute //Thiet lap second //Tra ve hour CMyTime(int h=0, int m=0, int s=0);
CMyTime(CMyTime & t);
void SetTime(int h, int m, int s);
void SetHour(int h);
void SetMinute(int m);
void SetSecond(int s);
//Cac ham get
int GetHour() const;
int GetMinute() const;
//Tra ve minute
int GetSecond() const; //Tra ve second
void Print() const; }; void CMyTime::SetSecond(int s)
{ CMyTime::CMyTime(int h, int m, int s)
{
#37 SetTime(h, m, s); second=(s>=0 && s<60)?s:0; }
CMyTime::CMyTime(CMyTime & t)
{ }
int CMyTime::GetHour() const
{ return hour; hour=t.hour;
minute=t.minute;
second=t.second; }
int CMyTime::GetMinute() const
{ return minute; }
void CMyTime::SetTime(int h, int m, int s)
{ }
int CMyTime::GetSecond() const
{ hour=(h>=0 && h<24)?h:0;
minute=(m>=0 && m<60)?m:0;
second=(s>=0 && s<60)?s:0; return second; }
void CMyTime::SetHour(int h)
{ }
void CMyTime::Print() const
{ hour=(h>=0 && h<24)?h:0; cout< } }
void CMyTime::SetMinute(int m)
{ minute=(m>=0 && m<60)?m:0; } #38 • Hàm thành viên hằng không được thay đổi đối tượng (tức là không sửa đổi giá trị của thành viên dữ liệu) • Hàm thành viên hằng có thể được đa năng hóa bởi phiên bản không hằng #39 • Phải cung cấp một bộ khởi tạo thành viên (member initializer)
cho constructor để khởi tạo giá trị ban đầu cho thành viên dữ
liệu đó • Nếu có nhiều thành viên dữ liệu hằng thì phải cung cấp nhiều bộ khởi tạo thành viên cách nhau bởi dấu phẩy #40 class CMyClass
{ private : CMyClass::CMyClass(int c, int a): x(a),
y(a)
{ int count;
const int x ,y; count = c; public: }
CMyClass (int c = 0, int a = 1); … }; Thành viên là đối tượng của lớp khác (1/5) #41 • Khi một đối tượng đi vào phạm vi, constructor của nó được gọi
một cách tự động Cần phải mô tả các tham số được truyền
tới các constructor của đối tượng thành viên • Các đối tượng thành viên được xây dựng theo thứ tự mà chúng được khai báo và trước đối tượng của lớp chứa chúng Thành viên là đối tượng của lớp khác (2/5) #42 class CDate
{ CDate::CDate (int d, int m, int y)
{ int day, month, year;
int TestDay (int d); public: month=((m >=1)&&( m<=12))?m:1;
year=y;
day=TestDay (d); } CDate ( int d =1 , int m=1, int y=1900);
void Print() const; };
void CDate::Print () const
{ cout << day<< "/"< } Thành viên là đối tượng của lớp khác (3/5) #43 int CDate::TestDay (int d)
{ static int days[]={31,28,31,30,31,30,31,31,30,31,30,31};
if ((d>0) && (d<=days [ month 1])) return d; if ((month==2) && (d==29)) if (( year % 400==0) || ((year % 10) && (year % 4==0))) d; return
1; return }
class CPerson
{ private: birth_day; char name[50];
CDate
CDate work_day; public : CPerson (char *st,int bday,int bmonth,int byear,int wday,int wmonth,int wyear);
void Print () const; }; Thành viên là đối tượng của lớp khác (4/5) #44 CPerson::CPerson (char *st,int bday,int bmonth,int byear,int wday,int wmonth,int wyear) : birth_day (bday, bmonth, byear), work_day (wday, wmonth, wyear)
{ strcpy (name, st); } void CPerson ::Print () const
{ cout <<"name:"< } Thành viên là đối tượng của lớp khác (5/5) #45 • Một đối tượng thành viên cần được khởi tạo thông qua một bộ khởi tạo thành viên • Nếu một bộ khởi tạo thành viên không được cung cấp thì
constructor mặc định của đối tượng thành viên sẽ được gọi một
cách tự động #46 • Được định nghĩa bên ngoài phạm vi của lớp đó Không phải là phương thức của lớp • Có quyền truy cập đến các thành viên private và protected #47 • Cú pháp: thêm từ khóa friend phía trước khai báo prototype của hàm trong định nghĩa lớp • Phân loại: • Hàm toàn cục (hàm tự do) • Hàm thành viên #48 class CCount
{ private: int x ; public: CCount ()
{ x = 0; }
friend void SetX (CCount &c, int val) ;
}; void SetX (CCount &c, int val)
{ c.x = val; } #49 class A; //Khai báo l p Aớ
class B
{ …
int fa(A x);
… }; class A
{ …
friend int B::fa(A x); }; #50 • Một lớp là friend của một lớp khác thì tất cả các hàm thành viên của lớp này đều là friend của lớp đó • Cú pháp: friend class_name; class B;
class A
{ …
friend class B;
… }; #51 • Xác định chính xác đối tượng nào đang gọi để nó truy cập đến đúng dữ liệu của đối tượng tương ứng • Mỗi đối tượng có một con trỏ this lưu địa chỉ của đối tượng (trỏ
đến chính nó) để khi mỗi lần gọi một hàm this được truyền
cho hàm đó để hàm biết chính xác đối tượng nào đang gọi #52 • Khi trong phương thức muốn trả về đối tượng đang gọi hàm • Phương thức cần lưu lại đối tượng cũ trước khi thay đổi dữ liệu • Để phân biệt thành viên dữ liệu trong đối tượng với biến của riêng hàm khi trùng tên #53 class A
{ class A
{ private:
int x; private:
int x; public: public: A(int a); A(int x); Trùng tên
(? phân biệt) … … };
A::A(int a)
{ };
A::A(int x)
{ this > x = a; this > x = x; } } #54 class CMyTime
{ private: int hour;
int minute;
int second; public: //Thiet lap CMyTime(int h=0, int m=0, int s=0);
CMyTime(CMyTime & t);
CMyTime & SetTime(int h, int m, int s);
CMyTime & SetHour(int h); hour //Thiet lap CMyTime & SetMinute(int m); minute //Thiet lap CMyTime & SetSecond(int s); second //Tra ve hour //Tra ve minute
//Tra ve second //Cac ham get
int GetHour() const;
int GetMinute() const;
int GetSecond() const;
void Print() const; };
CMyTime::CMyTime(int h, int m, int s)
{ SetTime(h, m, s); } #55 CMyTime::CMyTime(CMyTime & t)
{ hour=t.hour;
minute=t.minute;
second=t.second; }
CMyTime & CMyTime::SetTime(int h, int m, int s)
{ hour=(h>=0 && h<24)?h:0;
minute=(m>=0 && m<60)?m:0;
second=(s>=0 && s<60)?s:0;
return *this; }
CMyTime & CMyTime::SetHour(int h)
{ hour=(h>=0 && h<24)?h:0;
return *this; }
CMyTime & CMyTime::SetMinute(int m)
{ minute=(m>=0 && m<60)?m:0;
return *this; } CMyTime & CMyTime::SetSecond(int s)
#56
{ second=(s>=0 && s<60)?s:0;
return *this; }
int CMyTime::GetHour() const
{ CMyTime t; return hour; t.SetHour(18).SetMinute(30).SetSecond(0); }
int CMyTime::GetMinute() const
{ return minute; }
int CMyTime::GetSecond() const
{ return second; }
void CMyTime::Print() const
{ cout< } #57 • Mỗi đối tượng của một lớp có bản sao chép của chính nó cho tất cả các thành viên dữ liệu của lớp • Muốn có duy nhất một bản sao thành viên dữ liệu dùng chung cho tất cả các đối tượng của lớp fi #58 • Hàm thành viên muốn truy cập đến thành viên dữ liệu tĩnh thì hàm thành viên đó phải là hàm thành viên tĩnh • Các thành viên tĩnh có thể tồn tại ngay cả khi không có đối tượng của lớp đó • Muốn thành viên của lớp là thành viên tĩnh, thêm từ khóa static phía trước #59 • Thành viên dữ liệu tĩnh phải được khởi tạo trước khi sử dụng. Được khởi tạo bên ngoài lớp theo cú pháp: type class_name :: static_data_member_name = value; • Để truy cập thành viên tĩnh không thông qua đối tượng, thêm vào đầu tên lớp và toán tử định phạm vi • class_name :: static_data_member_name • class_name :: method_name (parameters) #60 • Các hàm thành viên không tĩnh có thể gọi hàm thành viên tĩnh nhưng ngược lại không được • Do hàm thành viên tĩnh là hàm độc lập với bất kỳ đối tượng nào (cid:0) Không có con trỏ this • Hàm thành viên tĩnh không được là hàm thành viên hằng #61 class CChicken
{ private: static int count; public: void main()
{ CChicken::CounterDisplay(); CChicken();
~CChicken();
static void CounterDisplay(); CChicken u;
u.CounterDisplay();
{ ở ộ CChicken v;
v.CounterDisplay(); };
int CChicken::count = 0; //Kh i đ ng
CChicken::CChicken()
{ } ++count; CChicken::CounterDisplay(); }
CChicken::~CChicken()
{ CChicken t;
t.CounterDisplay(); count; } }
void CChicken::CounterDisplay()
{ cout<<"Hien co "< } #62 ặ ọ ị CMyTime t1[2];//G i constructor m c đ nh t1[0].Print();
t1[1].Print(); ọ ố //G i constructor có tham s
CMyTime t2[2]={CMyTime(3,4,5),CMyTime(4,5,6)};
t2[0].Print();
t2[1].Print(); #63 • Các đối tượng có thể cấp phát động giống như các dữ liệu khác thông qua các toán tử new và delete • Toán tử new tự động gọi hàm constructor và toán tử delete tự động gọi destructor #64 CMyTime *t1,*t2; t1 = new CMyTime(); //t1 = new CMyTime;
t2 = new CMyTime(9,30,30);
t1>Print();
t2>Print();
delete t1;
delete t2; CMyTime *t = new CMyTime[10];
…
delete [] t; #65 • Khai báo một con trỏ trỏ đến thành viên của lớp class_name ::* pointer_name; • Lấy địa chỉ của một thành viên & class_name :: member_name Truy cập tới thành viên khi đối tượng của lớp &
thành viên của đối tượng đều xác định bởi con trỏ
Được sử dụng khi đối tượng được chỉ ra trực tiếp
còn các thành viên của nó thì được xác định nhờ
con trỏ #66 class A
{ A a;
int A::*px;
void (A::*pf)(); ỏ ỏ ế
//con tr tr đ n thành viên x
ỏ ỏ ế
//con tr tr đ n thành viên Print() public: x; px = &A::x;
pf = &A::Print; int
void Print()
{ cout<<"x="< } ế ậ a.x = 10;
cout< }; a.Print();
ọ
(a.*pf)(); //g i hàm Print() A *pa;
pa = &a;
pa>x = 20;
cout< #67 • Lớp đặc biệt được tham số sao cho chúng thể hiện một họ các lớp • Lớp này cũng mang đầy đủ ý tưởng của hàm template • Định nghĩa • template < class identifier >
class_declaration • template < typename identifier >
class_declaration #68 Định nghĩa hàm thành viên type_name class_name { … } Sử dụng class_name < type_name > object_name ; #69 template private: T x,y; CMyPoint public: CMyPoint(T x=0, T y=0);
void Display(); CMyPoint }; q=new CMyPoint r=new CMyPoint template s=new CMyPoint this>x=x;
this>y=y; } … template delete q;
delete r;
delete [] s; cout<<"Toa do:["< } #70 • Giống như hàm template, các lớp template cũng có các tham số kiểu và tham số biểu thức template template private: … T a[n] } …
public: CTable void Fun(); }; #71 • Tham số thực tương ứng với tham số biểu thức phải là hằng số • Hai lớp thực thể của cùng lớp template tương ứng với cùng một kiểu nếu • Các tham số kiểu tương ứng nhau một cách chính xác • Các tham số biểu thức có cùng giá trị #72 template private: T a[n] …
public: void Fun(); }; CTable template … } CTable #73 • Các lớp template và hàm template cũng cho phép khai báo friend • Hàm và lớp thông thường là friend template …
friend class A;
friend int Fun(int);
… }; #74 template … Một thực thể của hàm template
và lớp template là friend } ;
template … }
template …
friend class CMyPoint }; #75 Hàm template và lớp template là friend template … } ;
template … }
template …
template }; #76Thuộc tính truy xuất thành viên (1/3)
(member access specifier)
Thuộc tính truy xuất thành viên (2/3)
Thuộc tính truy xuất thành viên (3/3)
Sử dụng lớp đối tượng (1/4)
Sử dụng lớp đối tượng (2/4)
t1.SetTime(12, 5, 5);
t2.Print();
t3>SetTime(1, 5, 7);
t3>Print();
Sử dụng lớp đối tượng (3/4)
Sử dụng đối tượng (4/4)
Toán tử gán (1/2)
Toán tử gán (2/2)
Phương thức thiết lập (Constructor)
(1/9)
Phương thức thiết lập (2/9)
Đặc điểm
Phương thức thiết lập (3/9)
Phương thức thiết lập (4/9)
Có ba dạng
Phương thức thiết lập mặc định (5/9)
(Default Constructor)
Phương thức thiết lập mặc định (6/9)
Phương thức thiết lập sao chép (7/9)
(Copy Constructor)
Phương thức thiết lập sao chép (8/9)
Phương thức thiết lập sao chép (9/9)
Toán tử gán vs Constructor sao chép
Phương thức huỷ (Destructor) (1/4)
Phương thức huỷ (2/4)
Phương thức huỷ (3/4)
Phương thức huỷ (4/4)
Đối tượng hằng & thành viên hằng (1/7)
Đối tượng hằng & thành viên hằng (2/7)
Đối tượng hằng & thành viên hằng (3/7)
Đối tượng hằng & thành viên hằng (4/7)
Đối tượng hằng & thành viên hằng (5/7)
Đối tượng hằng & thành viên hằng (6/7)
Thành viên dữ liệu hằng
Đối tượng hằng & thành viên hằng
(7/7)
Hàm friend (1/4)
Hàm friend (2/4)
Hàm friend: Hàm toàn cục (3/4)
Hàm friend: Hàm thành viên (4/4)
Lớp friend
Con trỏ this (1/6)
Con trỏ this (2/6)
Khi nào sử dụng con trỏ this?
Con trỏ this (3/6)
Con trỏ this (4/6)
Con trỏ this (5/6)
Con trỏ this (6/6)
Thành viên tĩnh (static) (1/5)
Thành viên dữ liệu tĩnh: Có thể xem là biến toàn cục nhưng nằm
trong một lớp nào đó (độc lập với các đối tượng)
Thành viên tĩnh (2/5)
Thành viên tĩnh (3/5)
Thành viên tĩnh (4/5)
Thành viên tĩnh (5/5)
Mảng các đối tượng
Cấp phát động cho đối tượng (1/2)
Cấp phát động cho đối tượng (2/2)
Con trỏ xác định thành viên của lớp &
đối tượng (1/2)
->*
.*
Con trỏ xác định thành viên của lớp &
đối tượng (2/2)
Lớp template (1/9)
Lớp template (2/9)
Lớp template (3/9)
Lớp template (4/9)
Lớp template (5/9)
Lớp template (6/9)
Lớp template (7/9)
Lớp template (8/9)
Lớp template (9/9)
Q&A