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;

}

Thuộc tính truy xuất thành viên (1/3) (member access specifier)

#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

Thuộc tính truy xuất thành viên (2/3)

#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

Thuộc tính truy xuất thành viên (3/3)

#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

}

Sử dụng lớp đối tượng (1/4)

#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

Sử dụng lớp đối tượng (2/4)

#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;

t1.SetTime(12, 5, 5);

t2.Print();

t3­>SetTime(1, 5, 7);

t3­>Print();

Sử dụng lớp đối tượng (3/4)

#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)

Sử dụng đối tượng (4/4)

#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

Toán tử gán (1/2)

#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();

Toán tử gán (2/2)

#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ỏ

Phương thức thiết lập (Constructor) (1/9)

#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

Phương thức thiết lập (2/9)

#22

Đặc điểm

• 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

Phương thức thiết lập (3/9)

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<

}

Phương thức thiết lập (4/9)

#24

Có ba dạng

• Mặc định

• Sao chép

• Có tham số

Phương thức thiết lập mặc định (5/9) (Default Constructor)

#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”

Phương thức thiết lập mặc định (6/9)

#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();   …

};

};

Phương thức thiết lập sao chép (7/9) (Copy Constructor)

#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

Phương thức thiết lập sao chép (8/9)

#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;

} ...

Phương thức thiết lập sao chép (9/9)

#29

Toán tử gán vs Constructor sao chép

• 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

Phương thức huỷ (Destructor) (1/4)

#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

Phương thức huỷ (2/4)

#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ỏ

Phương thức huỷ (3/4)

#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

}

Phương thức huỷ (4/4)

#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:"<

}

Đối tượng hằng & thành viên hằng (1/7)

#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???

Đối tượng hằng & thành viên hằng (2/7)

#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

Đối tượng hằng & thành viên hằng (3/7)

#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;

};

Đối tượng hằng & thành viên hằng (4/7)

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;

}

Đối tượng hằng & thành viên hằng (5/7)

#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

Đối tượng hằng & thành viên hằng (6/7)

#39

Thành viên dữ liệu hằng

• 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

Đối tượng hằng & thành viên hằng (7/7)

#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

Hàm friend (1/4)

#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

Hàm friend (2/4)

#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

Hàm friend: Hàm toàn cục (3/4)

#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;

}

Hàm friend: Hàm thành viên (4/4)

#49

class  A; //Khai báo l p Aớ class  B {

… int  fa(A  x); …

};

class  A {

… friend  int  B::fa(A   x);

};

Lớp friend

#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; …

};

Con trỏ this (1/6)

#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

Con trỏ this (2/6)

#52

Khi nào sử dụng con trỏ this?

• 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

Con trỏ this (3/6)

#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;

}

}

Con trỏ this (4/6)

#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);

}

Con trỏ this (5/6)

#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;

}

Con trỏ this (6/6)

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<

}

Thành viên tĩnh (static) (1/5)

#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

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)

#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

Thành viên tĩnh (3/5)

#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)

Thành viên tĩnh (4/5)

#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

Thành viên tĩnh (5/5)

#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 "<

}

Mảng các đối tượng

#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();

Cấp phát động cho đối tượng (1/2)

#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

Cấp phát động cho đối tượng (2/2)

#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;

Con trỏ xác định thành viên của lớp & đối tượng (1/2)

#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ỏ

Con trỏ xác định thành viên của lớp & đối tượng (2/2)

#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<*px<*pf)();

Lớp template (1/9)

#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

Lớp template (2/9)

#68

Định nghĩa hàm thành viên

type_name class_name :: method_name ( parameters )

{

}

Sử dụng

class_name < type_name > object_name ;

Lớp template (3/9)

#69

template  class CMyPoint {

private:

T x,y;

CMyPoint  p(10,2); p.Display();

public:

CMyPoint(T x=0, T y=0); void Display();

CMyPoint  *q, *r, *s;

};

q=new CMyPoint;

r=new CMyPoint();

template   CMyPoint::CMyPoint(T  x, T  y) {

s=new CMyPoint[10];

this­>x=x; this­>y=y;

}

template   void CMyPoint::Display() {

delete q; delete r; delete [] s;

cout<<"Toa do:["<

}

Lớp template (4/9)

#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  class CTable {

template  void CTable::Fun() {

private:

T  a[n]

}

… public:

CTable  x;

void Fun();

};

Lớp template (5/9)

#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ị

Lớp template (6/9)

#72

template  class CTable {

private:

T  a[n]

… public:

void Fun();

};

CTable  t1; CTable  t2; t2 = t1; //Error CTable  t3; CTable  t4; t4 = t3; //Error CTable  t5; CTable  t6; t6 = t5; //OK

template  void CTable::Fun() {

}

CTable  x;

Lớp template (7/9)

#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   class CMyClass {

… friend class A; friend  int  Fun(int); …

};

Lớp template (8/9)

#74

template  class CMyPoint {

Một thực thể của hàm template và lớp template là friend

} ; template  int F(T a) {

} template  class CMyClass {

… friend class CMyPoint; friend  int  F(float); …

};

Lớp template (9/9)

#75

Hàm template và lớp template là friend

template  class CMyPoint {

} ; template  int F(T a) {

} template  class CMyClass {

… template friend class CMyPoint; template friend  int  F(U); …

};

Q&A

#76