Giáo trình Lập trình hướng đối tượng - Lê Thị Mỹ Hạnh

MỤC LỤC

X W

CHƯƠNG 1: GIỚI THIỆU VỀ LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG. 5

I. LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG (OOP) LÀ GÌ ? . 5

I.1. Lập trình tuyến tính . 5

I.2. Lập trình cấu trúc. 5

I.3. Sự trừu tượng hóa dữ liệu. 6

I.4. Lập trình hướng đối tượng . 6

II. MỘT SỐ KHÁI NIỆM MỚI TRONG LẬP TRÌNH HƯỚNG ĐỐI TƯỢNG. 8

II.1. Sự đóng gói (Encapsulation) . 8

II.2. Tính kế thừa (Inheritance) . 9

II.3. Tính đa hình (Polymorphism) . 10

III. CÁC NGÔN NGỮ VÀ VÀI ỨNG DỤNG CỦA OOP. 11

CHƯƠNG 2: CÁC MỞ RỘNG CỦA C++ . 12

I. LỊCH SỬ CỦA C++ . 12

II. CÁC MỞ RỘNG CỦA C++. 12

II.1. Các từ khóa mới của C++. 12

II.2. Cách ghi chú thích. 12

II.3. Dòng nhập/xuất chuẩn. 13

II.4. Cách chuyển đổi kiểu dữ liệu . 14

II.5. Vị trí khai báo biến. 14

II.6. Các biến const. 15

II.7. Về struct, union và enum. 16

II.8. Toán tử định phạm vi . 16

II.9. Toán tử new và delete. 17

II.10. Hàm inline . 23

II.11. Các giá trị tham số mặc định . 24

II.12. Phép tham chiếu . 25

II.13. Phép đa năng hóa (Overloading). 29

CHƯƠNG 3: LỚP VÀ ĐỐI TƯỢNG . 39

I. DẪN NHẬP. 39

II. CÀI ĐẶT MỘT KIỂU DO NGƯỜI DÙNG ĐỊNH NGHĨA VỚI MỘT STRUCT. 39

III. CÀI ĐẶT MỘT KIỂU DỮ LIỆU TRỪU TƯỢNG VỚI MỘT LỚP. 41

IV. PHẠM VI LỚP VÀ TRUY CẬP CÁC THÀNH VIÊN LỚP . 45

V. ĐIỀU KHIỂN TRUY CẬP TỚI CÁC THÀNH VIÊN . 47

VI. CÁC HÀM TRUY CẬP VÀ CÁC HÀM TIỆN ÍCH. 48

VII. KHỞI ĐỘNG CÁC ĐỐI TƯỢNG CỦA LỚP : CONSTRUCTOR. 49

VIII.SỬ DỤNG DESTRUCTOR. 51

IX. KHI NÀO CÁC CONSTRUTOR VÀ DESTRUCTOR ĐƯỢC GỌI ? . 53

X. SỬ DỤNG CÁC THÀNH VIÊN DỮ LIỆU VÀ CÁC HÀM THÀNH VIÊN . 54

XI. TRẢ VỀ MỘT THAM CHIẾU TỚI MỘT THÀNH VIÊN DỮ LIỆU PRIVATE. 57

XII. PHÉP GÁN BỞI TOÁN TỬ SAO CHÉP THÀNH VIÊN MẶC ĐỊNH . 59

XIII.CÁC ĐỐI TƯỢNG HẰNG VÀ CÁC HÀMTHÀNH VIÊN CONST. 60

XIV.LỚP NHƯ LÀ CÁC THÀNH VIÊN CỦA CÁC LỚP KHÁC . 64

XV. CÁC HÀM VÀ CÁC LỚP FRIEND. 67Giáo trình môn Lập trình hướng đối tượng Trang

3

XVI.CON TRỎ THIS . 68

XVII.CÁC ĐỐI TƯỢNG ĐƯỢC CẤP PHÁT ĐỘNG . 71

XVIII.CÁC THÀNH VIÊN TĨNH CỦA LỚP. 72

CHƯƠNG 4: ĐA NĂNG HÓA TOÁN TỬ. 76

I. DẪN NHẬP. 76

II. CÁC NGUYÊN TẮC CƠ BẢN CỦA ĐA NĂNG HÓA TOÁN TỬ. 76

III. CÁC GIỚI HẠN CỦA ĐA NĂNG HÓA TOÁN TỬ. 76

IV. CÁC HÀM TOÁN TỬ CÓ THỂ LÀ CÁC THÀNH VIÊN CỦA LỚP HOẶC

KHÔNG LÀ CÁC THÀNH VIÊN. 77

V. ĐA NĂNG HOÁ CÁC TOÁN TỬ HAI NGÔI . 80

VI. ĐA NĂNG HÓA CÁC TOÁN TỬ MỘT NGÔI . 87

VII. ĐA NĂNG HÓA MỘT SỐ TOÁN TỬ ĐẶC BIỆT . 90

VII.1.Toán tử [] . 91

VII.2.Toán tử () . 92

VIII.TOÁN TỬ CHUYỂN ĐỔI KIỂU. 94

IX. TOÁN TỬ NEW VÀ DELETE. 95

IX.1.Đa năng hóa toán tử new và delete toàn cục. 96

IX.2.Đa năng hóa toán tử new và delete cho một lớp . 97

X. ĐA NĂNG HÓA CÁC TOÁN TỬ CHÈN DÒNG << VÀ TRÍCH DÒNG >> . 98

XI. MỘT SỐ VÍ DỤ . 99

XI.1.Lớp String. 99

XI.2.Lớp Date. 103

CHƯƠNG 5: TÍNH KẾ THỪA. 107

I. DẪN NHẬP. 107

II. KẾ THỪA ĐƠN . 107

II.1.Các lớp cơ sở và các lớp dẫn xuất . 107

II.2.Các thành viên protected. 109

II.3.Ép kiểu các con trỏ lớp cơ sở tới các con trỏ lớp dẫn xuất. 109

II.4.Định nghĩa lại các thành viên lớp cơ sở trong một lớp dẫn xuất:. 113

II.5.Các lớp cơ sở public, protected và private. 113

II.6.Các contructor và destructor lớp dẫn xuất. 113

II.7.Chuyển đổi ngầm định đối tượng lớp dẫn xuất sang đối tượng lớp cơ sở. 116

III. ĐA KẾ THỪA (MULTIPLE INHERITANCE). 116

IV. CÁC LỚP CƠ SỞ ẢO (VIRTUAL BASE CLASSES) . 119

CHƯƠNG 6: TÍNH ĐA HÌNH . 122

I. DẪN NHẬP. 122

II. PHƯƠNG THỨC ẢO (VIRTUAL FUNCTION) . 122

III. LỚP TRỪU TƯỢNG (ABSTRACT CLASS) . 125

IV. CÁC THÀNH VIÊN ẢO CỦA MỘT LỚP. 127

IV.1.Toán tử ảo. 127

IV.2.Có constructor và destructor ảo hay không?. 129

CHƯƠNG 7: THIẾT KẾ CHƯƠNG TRÌNH THEO HƯỚNG ĐỐI TƯỢNG . 132

I. DẪN NHẬP. 132

II. CÁC GIAI ĐOẠN PHÁT TRIỂN HỆ THỐNG. 132

III. CÁCH TÌM LỚP . 133

IV. CÁC BƯỚC CẦN THIẾT ĐỂ THIẾT KẾ CHƯƠNG TRÌNH. 133

V. CÁC VÍ DỤ . 134Giáo trình môn Lập trình hướng đối tượng Trang

Biên soạn: Lê Thị Mỹ Hạnh

4

CHƯƠNG 8: CÁC DẠNG NHẬP/XUẤT. 143

I. DẪN NHẬP. 143

II. CÁC DÒNG(STREAMS) . 143

II.1.Các file header của thư viện iostream. 143

II.2.Các lớp và các đối tượng của dòng nhập/xuất. 144

III. DÒNG XUẤT. 145

III.1.Toán tử chèn dòng . 145

III.2.Nối các toán tử chèn dòng và trích dòng. 146

III.3.Xuất ký tự với hàm thành viên put(); Nối với nhau hàm put() . 147

IV. DÒNG NHẬP. 148

IV.1.Toán tử trích dòng:. 148

IV.2.Các hàm thành viên get() và getline() . 149

IV.3.Các hàm thành viên khác của istream . 151

IV.4.Nhập/xuất kiểu an toàn. 151

V. NHẬP/XUẤT KHÔNG ĐỊNH DẠNG VỚI READ(),GCOUNT() VÀ WRITE() 151

VI. DÒNG NHẬP/ XUẤT FILE . 152

VI.1.Nhập/xuất file văn bản . 154

CHƯƠNG 9: HÀM VÀ LỚP TEMPLATE. 159

I. CÁC HÀM TEMPLATE. 159

II. CÁC LớP TEMPLATE. 161

pdf165 trang | Chia sẻ: hienduc166 | Lượt xem: 715 | Lượt tải: 1download
Bạn đang xem trước 20 trang tài liệu Giáo trình Lập trình hướng đối tượng - Lê Thị Mỹ Hạnh, để xem tài liệu hoàn chỉnh bạn click vào nút TẢI VỀ ở trên
ọi hàm này, trình biên dịch tự động phát sinh các hàm mã đối tượng riêng biệt để xử 
lý mỗi kiểu của lời gọi thích hợp. Trong C, điều này có thể được thực hiện bằng cách sử dụng các macro tạo 
với tiền xử lý #define. Tuy nhiên, các macro biểu thị khả năng đối với các hiệu ứng lề nghiêm trọng và 
không cho phép trình biên dịch thực hiện việc kiểm tra kiểu. Các hàm template cung cấp một giải pháp mạch 
lạc giống như các macro, nhưng cho phép kiểm tra kiểu đầy đủ. Chẳng hạn, chúng ta muốn viết hàm lấy trị 
tuyệt đối của một số, chúng ta có thể viết nhiều dạng khác nhau như sau: 
int MyAbs(int X) 
{ 
return X>=0?X:-X; 
} 
long MyAbs(long X) 
{ 
return X>=0?X:-X; 
} 
double MyAbs(double X) 
{ 
return X>=0?X:-X; 
} 
Tuy nhiên với các hàm này chúng ta vẫn chưa có giải pháp tốt, mang tính tổng quát nhất như hàm có 
tham số kiểu int nhưng giá trị trả về là double và ngược lại. 
Tất cả các hàm template định nghĩa bắt đầu với từ khóa template theo sau một danh sách các tham số 
hình thức với hàm template vây quanh trong các ngoặc nhọn (); Mỗi tham số hình thức phải được đặt 
trước bởi từ khóa class như: 
template 
hoặc template 
Các tham số hình thức của một định nghĩa template được sử dụng để mô tả các kiểu của các tham số cho 
hàm, để mô tả kiểu trả về của hàm, và để khai báo các biến bên trong hàm. Phần định nghĩa hàm theo sau và 
được định nghĩa giống như bất kỳ hàm nào. Chú ý từ khóa class sử dụng để mô tả các kiểu tham số của hàm 
template thực sự nghĩa là "kiểu có sẵn và kiểu người dùng định nghĩa bất kỳ". 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
160
Khi đó, hàm trị tuyệt đối ở trên viết theo hàm template: 
template 
T MyAbs(T x) 
{ 
return (x>=0)?x:-x; 
} 
Hàm template MyAbs() khai báo một tham số hình thức T cho kiểu của một số. T được tham khảo như 
một tham số kiểu. Khi trình biên dịch phát hiện ra một lời gọi hàm MyAbs() trong chương trình, kiểu của 
tham số thứ nhất của hàm MyAbs() được thay thế cho T thông qua định nghĩa template, và C++ tạo một hàm 
template đầy đủ để trả về trị tuyệt đối của một số của kiểu dữ liệu đã cho. Sau đó, hàm mới tạo được biên 
dịch. Chẳng hạn: 
cout<<MyAbs(-2)<<endl; 
cout<<MyAbs(3.5)<<endl; 
Trong lần gọi thứ nhất, hàm MyAbs() có tham số thực là int nên trình biên dịch tạo ra hàm int 
MyAbs(int) theo dạng của hàm template, lần thứ hai sẽ tạo ra hàm float MyAbs(float). 
Mỗi tham số hình thức trong một định nghĩa hàm template phải xuất hiện trong danh sách tham số của 
hàm tối thiểu một lần. Tên của tham số hình thức chỉ có thể sử dụng một lần trong danh sách tham số của 
phần đầu template. 
Ví dụ 9.1: Sử dụng hàm template để in các giá trị của một mảng có kiểu bất kỳ. 
1: //Chương trình 9.1 
2: #include 
3: 
4: template 
5: void PrintArray(T *Array, const int Count) 
6: { 
7: for (int I = 0; I < Count; I++) 
8: cout << Array[I] << " "; 
9: 
10: cout << endl; 
11: } 
12: 
13: int main() 
14: { 
15: const int Count1 = 5, Count2 = 7, Count3 = 6; 
16: int A1[Count1] = {1, 2, 3, 4, 5}; 
17: float A2[Count2] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7}; 
18: char A3[Count3] = "HELLO"; 
19: cout << "Array A1 contains:" << endl; 
20: PrintArray(A1, Count1); //Hàm template kiểu int 
21: cout << "Array A2 contains:" << endl; 
22: PrintArray(A2, Count2); //Hàm template kiểu float 
23: cout << "Array A3 contains:" << endl; 
24: PrintArray(A3, Count3); //Hàm template kiểu char 
25: return 0; 
26: } 
Chúng ta chạy ví dụ 9.1, kết quả ở hình 9.1 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
161
Hình 9.1: Kết quả của ví dụ 9.1 
Ví dụ 9.2: Hàm template có thể có nhiều tham số. 
1: //Chương trình 9.2 
2: #include 
3: 
4: template 
5: T Max(T a, T b) 
6: { 
7: return (a>b)?a:b; 
8: } 
9: 
10: int main() 
11: { 
12: float A,B; 
13: cout<<"Enter first number:"; 
14: cin>>A; 
15: cout<<"Enter second number:"; 
16: cin>>B; 
17: cout<<"Maximum:"<<Max(A,B); 
18: return 0; 
19: } 
Chúng ta chạy ví dụ 9.2, kết quả ở hình 9.2 
Hình 9.2: Kết quả của ví dụ 9.2 
Một hàm template có thể được đa năng hóa theo vài cách. Chúng ta có thể cung cấp các hàm template 
khác mà mô tả cùng tên hàm nhưng các tham số hàm khác nhau. Một hàm template cũng có thể được đa 
năng hóa bởi cung cấp hàm non-template với cùng tên hàm nhưng các tham số hàm khác nhau. Trình biên 
dịch thực hiện một xử lý so sánh để xác định hàm gọi khi một hàm được gọi. Đầu tiên trình biên dịch cố 
gắng tìm và sử dụng một đối sánh chính xác mà các tên hàm và các kiểu tham số đối sánh chính xác. Nếu 
điều này thất bại, trình biên dịch kiểm tra nếu một hàm template đã có mà có thể phát sinh một hàm template 
với một đối sánh chính xác của tên hàm và các kiểu tham số. Nếu một hàm template như thế được tìm thấy, 
trình biên dịch phát sinh và sử dụng hàm template thích hợp. Chú ý xử lý đối sánh này với các template đòi 
yêu các đối sánh chính xác trên tất cả kiểu tham số-không có các chuyển đổi tự động được áp dụng. 
II. Các lớp template 
Bên cạnh hàm template, ngôn ngữ C++ còn trang bị thêm lớp template, lớp này cũng mang đầy đủ ý 
tưởng của hàm template. Các lớp template được gọi là các kiểu có tham số (parameterized types) bởi vì 
chúng đòi hỏi một hoặc nhiều tham số để mô tả làm thế nào tùy chỉnh một lớp template chung để tạo thành 
một lớp template cụ thể. 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
162
Chúng ta cài đặt một lớp Stack, thông thường chúng ta phải định nghĩa trước một kiểu dữ liệu cho từng 
phần tử của stack. Nhưng điều này chỉ mang lại sự trong sáng cho một chương trình và không giải quyết 
được vấn đề tổng quát. Do đó chúng ta định nghĩa lớp template Stack. 
Ví dụ 9.3: 
File TSTACK.H: 
1: //TSTACK.H 
2: //Lớp template Stack 
3: #ifndef TSTACK_H 
4: #define TSTACK_H 
5: 
6: #include 
7: 
8: template 
9: class Stack 
10: { 
11: private: 
12: int Size; //Kích thước stack 
13: int Top; 
14: T *StackPtr; 
15: public: 
16: Stack(int = 10); 
17: ~Stack() 
18: { 
19: delete [] StackPtr; 
20: } 
21: int Push(const T&); 
22: int Pop(T&); 
23: int IsEmpty() const 
24: { 
25: return Top == -1; 
26: } 
27: int IsFull() const 
28: { 
29: return Top == Size - 1; 
30: } 
31: }; 
32: 
33: template 
34: Stack::Stack(int S) 
35: { 
36: Size = (S > 0 && S < 1000) ? S : 10; 
37: Top = -1; 
38: StackPtr = new T[Size]; 
39: } 
40: 
41: template 
42: int Stack::Push(const T &Item) 
43: { 
44: if (!IsFull()) 
45: { 
46: StackPtr[++Top] = Item; 
47: return 1; 
48: } 
49: return 0; 
50: } 
51: 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
163
52: template 
53: int Stack::Pop(T &PopValue) 
54: { 
55: if (!IsEmpty()) 
56: { 
57: PopValue = StackPtr[Top--]; 
58: return 1; 
59: } 
60: return 0; 
61: } 
62: 
63: #endif 
File CT9_3.CPP: 
1: //CT9_3.CPP 
2: //Chương trình 9.3 
3: #include "tstack.h" 
4: 
5: int main() 
6: { 
7: Stack FloatStack(5); 
8: float F = 1.1; 
9: cout << "Pushing elements onto FloatStack" << endl; 
10: while (FloatStack.Push(F)) 
11: { 
12: cout << F << ' '; 
13: F += 1.1; 
14: } 
15:cout << endl << "Stack is full. Cannot push " << F << endl 
16: << endl << "Popping elements from FloatStack" << endl; 
17: while (FloatStack.Pop(F)) 
18: cout << F << ' '; 
19: cout << endl << "Stack is empty. Cannot pop" << endl; 
20: Stack IntStack; 
21: int I = 1; 
22: cout << endl << "Pushing elements onto IntStack" << endl; 
23: while (IntStack.Push(I)) 
24: { 
25: cout << I << ' '; 
26: ++I ; 
27: } 
28:cout << endl << "Stack is full. Cannot push " << I << endl 
29: << endl << "Popping elements from IntStack" << endl; 
30: while (IntStack.Pop(I)) 
31: cout << I << ' '; 
32: cout << endl << "Stack is empty. Cannot pop" << endl; 
33: return 0; 
34: } 
Chúng ta chạy ví dụ 9.3, kết quả ở hình 9.3 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
164
Hình 9.3: Kết quả của ví dụ 9.3 
Hàm thành viên định nghĩa bên ngoài lớp template bắt đầu với phần đầu là 
template 
Sau đó mỗi định nghĩa tương tự một định nghĩa hàm thường ngoại trừ kiểu phần tử luôn luôn được liệt 
kê tổng quát như tham số kiểu T. Chẳng hạn: 
template 
int Stack::Push(const T &Item) 
{ 
. 
} 
Ngôn ngữ C++ còn cho phép chúng ta tạo ra các lớp template linh động hơn bằng cách cho phép thay 
đổi giá trị của các thành viên dữ liệu bên trong lớp. Khi đó lớp có dạng của một hàm với tham số hình thức. 
BÀI TẬP 
Bài 1: Viết hàm template trả về giá trị trung bình của một mảng, các tham số hình thức của hàm này là 
tên mảng và kích thước mảng. 
Bài 2: Cài đặt hàng đợi template. 
Bài 3: Cài đặt lớp template dùng cho cây nhị phân tìm kiếm (BST). 
Bài 4: Cài đặt lớp template cho vector để quản lý vector các thành phần có kiểu bất kỳ. 
Bài 5: Viết hàm template để sắp xếp kiểu dữ liệu bất kỳ. 
Bài 6: Trong C++, phép toán new được dùng để cấp phát bộ nhớ, khi không cấp phát được con trỏ có 
giá trị NULL. Hãy cài đặt lại các lớp Matrix và Vector trong đó có bổ sung thêm thành viên là lớp exception 
với tên gọi là Memory để kiểm tra việc cấp phát này. 
Giáo trình môn Lập trình hướng đối tượng Trang 
Biên soạn: Lê Thị Mỹ Hạnh 
165
TÀI LIỆU THAM KHẢO 
X	W 
[1] Lập trình hướng đối tượng C++ của Nguyễn Thanh Thuỷ 
[2] Lập trình hướng đối tượng C++ của Trần Văn Lăng 
[3] C++ Kỹ thuật và Ứng dụng – Scott Robert Ladd 
[4] Ngôn ngữ lập trình C và C++ 
[5] Bài tập Lập trình hướng đối tượng - Nguyễn Thanh Thuỷ 
[6] Introduction to Object-Oriented Programming Using C++ - Peter Müller 
[7] .. 

File đính kèm:

  • pdfGtrinhOOP.pdf
Bài giảng liên quan