- TÝnh t¬ng øng béi cßn thÓ hiÖn khi mét hµm thµnh phÇn trong líp c¬ së ®îc gäi tõ mét ®èi tîng líp dÉn xuÊt, cßn b¶n th©n hµm ®ã th× gäi tíi hµm thµnh phÇn ® îc ®Þnh nghÜa ®ång thêi tro[r]
(1)Bài giảng lập trình hớng đối tợng (object oriented programming - oop)
Chơng1 lập trình hớng i tng
1 Phơng pháp lập trình 1.1.Lập tr×nh tuyÕn tÝnh
- Là phơng pháp đợc phát triển vào ngày đầu ngành khoa học máy tính, chơng trình cịn thơ sơ
- Một chơng trình bao gồm nhiều dịng lệnh đợc thực theo trật tự tuyến tính Trong chơng trình khơng có thủ tục đoạn lệnh thờng đợc chép lặp lại chúng đợc dùng chơng trình nhiều lần, chơng trình có khuynh hớng dài Hơn ngơn ngữ lập trình truyến tính khơng có khả kiểm sốt phạm vi nhìn thấy liệu Mọi liệu chơng trình liệu tồn cục, có nghĩa chúng bị sửa đổi phần chơng trình Việc dị tìm thay đổi không mong muốn phần tử liệu dãy mã lệnh dài vòng làm cho thảo chơng trình viên tốn thời gian
1.2 LËp tr×nh cÊu tróc
- Khi ngành khoa học máy tính phát triển nhiều ứng dụng máy tính đợc đa vào phục vụ sản xuất Lúc này, chơng trình trở nên lớn phức tạp Khi đó, lập trình tuyến tính khơng đáp ứng đợc yêu cầu phát triển phần mểm lập trình cấu trúc đời
- Phơng pháp đợc phát triển mạnh mẽ vào thập kỷ 70 Về chất, chơng trình đợc chia nhỏ thành thủ tục riêng rẽ (hay gọi hàm thực cơng việc rời rạc q trình lớn phức tạp) Các thủ tục đợc thiết kế độc lập tốt, chúng chuyển giao thông tin cho đối số vào-ra Mỗi thủ tục tự quản lý biến địa phơng khơng cho phạm vi thủ tục đợc xâm phạm Nh hệ thống đợc xem nh tiến trình phân tích thành nhiều tiến trình nhỏ hn
- Quan điểm LTCT: Chơng trình = Dữ liệu + Giải thuật
- S trỡu tng hoá (abstraction) chức khái niệm đợc đa vào lập trình có cấu trúc Trong chơng trình có cấu trúc, cần biết thủ tục cho làm đ-ợc cơng việc đủ Cịn làm mà cơng việc lại thực đ đ-ợc khơng quan trọng, mà thủ tục cịn tin cậy đợc đợc dùng mà khơng cần biết phải để hồn thành đắn chức
(2)1.3 Lập trình hớng đối tợng
- Khái niệm “hớng đối tợng” đợc xây dựng tảng khái niệm “lập trình có cấu trúc” “sự trừu tợng hố liệu” Sự trừu tợng hố liệu (Data Abstraction) có nghĩa cấu trúc liệu phần tử đợc sử dụng mà khơng cần để ý đến chi tiết cụ thể mà ngời ta xây dựng Ví dụ, số thực dấu phẩy động đợc trừu tợng hoá tất ngơn ngữ lập trình, khơng cần để ý đến biểu diễn nhị phân cụ thể số thực gán giá trị cho nó, khơng cần phải biết thay đổi phép nhân nhị phân nhân số thực Điều quan trọng số thực làm hiểu đợc
- Điểm phơng pháp lập trình HĐT thiết kế hệ thống xoay quanh liệu Nghĩa là, lúc thao tác xử lý hệ thống đợc gắn liền với liệu Chính gắn kết liệu hàm xử lý mà khả modul hoá cao liệu đối tợng thay đổi thỉ có hàm xử lý đối tợng thay đổi mà thơi Rõ ràng, lúc ta thấy đợc u điểm rõ rệt phơng pháp lập trình hớng đối tợng so với lập trình có cấu trúc Sự đóng gói liệu hàm xử lý vào khối đ ợc gọi đối tợng
- Để hiểu rõ phơng pháp lập trình này, xét tốn “quan hệ gia đình” với yêu cầu làm để thể đợc mối quan hệ thành viên gia đình máy tính trả lời đợc câu hỏi dạng tổng quát: “A B có quan hệ nh gia đình ?” với A B hai cá thể
2 Bài tốn quan hệ gia đình
- Trong xã hội, ngời có gia đình, tồn nhiều mối quan hệ gia đình phức tạp nh ơng, bà, cha, mẹ, cơ, chú, bác, Thông thờng để thể mối quan hệ ngời ta biểu diễn sơ đồ cây, ví dụ biểu diễn quan hệ gia đình với ba hệ nh sau:
Hình 1.1.Cây quan hệ gia đình
2.1.TiÕp cận theo theo phơng pháp LTCT
- u tiờn phải xây dựng cấu trúc liệu thể đợc quan hệ Xét qua có vẽ đơn giản nhng khơng hồn tồn đơn giản địi hỏi ngời lập trình phải thành thạo sử dụng trỏ, phải xây dựng đợc giải thuật cập nhật thông tin quan hệ, Các giải thuật tơng đối phức tạp cấu trúc liệu toán Yêu cầu toán trả lời đợc câu hỏi dạng nh “Hng Mai có quan hệ nh ?”
Mr.Thắng Ms.Nga
Mr.Quang Ms.Vân Mr.Tuấn Ms.Hằng
(3)Câu trả lời chơng trình phải “Hng anh Mai” Để thực đợc nh vậy, rõ ràng cần phải xây dựng đợc giải thuật tìm đợc mối quan hệ hai nút quan hệ Một vấn đề phức tạp tên gọi cho mối quan hệ gia đình Việt nam phong phú, khó để vét cạn hết mối quan hệ có quan hệ Hơn cần phát triển, chơng trình phải quản lý đợc nhiều gia đình lúc gia đình có mối quan hệ thơng gia với Hình 1.2 sơ đồ quan hệ đợc phát triển từ sơ đồ để minh hoạ cho vấn đề
- Một câu hỏi đặt là: “Liệu với cấu trúc liệu cũ có đảm bảo giải đợc vấn đề này không ?” Rõ ràng câu trả lời “không” Sơ đồ quan hệ hình vẽ phải mơ tả quan hệ gia đình Chỉ với chút thay đổi cấu trúc liệu dẫn đến loạt vấn đề đòi hỏi phải viết lại giải thuật chơng trình
2.2 TiÕp cËn theo LTH§T
- Bài tốn quan hệ gia đình đợc xem xét dới mức độ quản lý tập đối tợng Con ngời Để biết mối quan hệ gia đình cá thể, cần thể số quan hệ nh cha, mẹ, anh em, cái, vợ chồng cá thể Nh vậy, đối tợng ngời tốn có thuộc tính riêng, nói lên cha, mẹ, anh em, họ Ngoài cần có thuộc tính cho biết tên cá thể ? Nh vậy, mô tả lớp đối tợng ngời nh sau:
Nếu nh chẳng khác cấu trúc hay ghi cấu trúc liệu đ -ợc sử dụng phơng pháp lập trình cấu trúc Vấn đề phơng pháp LTHĐT xem mối quan hệ gia đình đợc hình thành cách tự nhiên kiện cụ thể sống tạo nên Ví dụ: Khi ngời phụ nữ sinh con, đứa cô ta sinh có mẹ ta bố chồng cô ta, đồng thời anh chồng phải đợc cập nhật để có thêm đứa Những đứa trớc ta có thêm đứa em đứa bé có thêm ng ời anh ngời chị Dễ dàng thấy có hai kiện tác động đến mối quan hệ gia đình sinh ngơì phụ nữ nhân hai cá thể khác giới xã hội Các
Con ng êi Tªn? Cha? MĐ? Anh em?
Con cái? Vợ/chồng?
Mr.Thắng Ms.Nga
Mr.Quang
g Ms.V©n Mr.TuÊn Ms.H»ng
Mr.H ng Mss.Trang Miss.Mai
Mr.Thµnh Ms.Lan
(4)kiện gắn liền với đứa toán Điều có nghĩa nói đến kiện phải đợc phát sinh ngời Ví dụ: Khi nói đến kiện sinh phải biết ngời sinh Khi kiện ngời xẩy (ví dụ nh sinh con) thuộc tính ta bị thay đổi, đồng thời thuộc tính số đối tơng liên quan thay đổi Q trình đóng gói kiện thuộc tính tạo đối tợng – khái niệm lập trình hớng đối tợng Một mơ tả chung cho đối tợng ngời toán đợc gọi lớp và đợc minh hoạ nh sau:
Sau gắn kết đối tợng trên, vấn đề tạo sơ đồ quan hệ gia đình nh Ví dụ: Giả thiết có hai đối tợng ơng Thắng bà Nga, quan hệ gia đình đợc mơ tả nh sau:
Các kiện để tạo quan hệ đợc mơ tả theo trật tự sau: Thắng.cới(Nga)
Nga.sinh (gai, V©n) Nga.sinh (trai, TuÊn)
Các kiện viết theo cú pháp sau:
Đối tợng tạo kiện Sự kiện (thông số kèm theo sù kiÖn).
- Nh dễ thấy không cần phải quan tâm đến cách tạo cấu trúc quan hệ nh bên liệu chơng trình mà cung cấp liệu tốn cho chơng trình thông qua kiện nh
- Trở lại vấn đề tốn trả lời câu hỏi mơi quan hệ gia đình nh tiếp cận toán theo phơng pháp Để trả lời đợc câu hỏi tổng quát “X Y có quan hệ gia đình nh nào?” ta cần trả lời câu hỏi nhỏ nh “X có phải anh Y khơng?”, “X có phải ông nội Y không?” v.v Câu hỏi nhìn từ góc độ đối tợng X nh: “ đối tợng có phải anh Y khơng?”, “đối tợng có phải ơng nội Y khơng”
Con ng êi Tªn? Cha? MĐ? Anh em? Con cái? Vợ/chồng?
Sinh C ới
Mr.Thắng Ms.Nga
(5)v.v Nh câu hỏi lúc chuyển đối tợng đợc trả lời Các đối tợng lúc cần có phơng thức để trả lời câu hỏi nh vậy, lớp đối tợng ngời đợc minh hoạ nh sau:
Ta xem xét đối tợng trả lời câu hỏi nh nào? Chẳng hạn X trả lời câu hỏi “đối t-ợng có phải anh Y không?” Để trả lời, cần kiểm tra xem Y có phải anh mà thuộc tính lu giữ khơng Tơng tự câu hỏi quan hệ gần nh em, chị, bố, mẹ, Còn câu hỏi nh “đối tợng có phải ơng nội Y khơng?” Để trả lời, ta phải dựa vào kết trả lời câu hỏi quan hệ gần Để biết đ ợc X ông nội Y phải ngời Z mà X bố Z Z bố Y Nếu khơng đợc Z X là ông nội Y Việc tìm kiếm Z tơng đối đơn giản chơng trình quản lý tập đối tợng ngời tìm Z tập đối tợng ngời Tóm lại vấn đề toán đợc giải tiếp cận phơng pháp lập trình hớng đối tợng Dễ thấy tốn đợc phân tích gần với thực tế tự nhiên
3 Lập trình hớng đối tợng
- LTHTĐ đặt trọng tâm vào đối tợng, yếu tố quan trọng việc phát triển chơng trình khơng cho phép liệu biến động tự hệ thống Dữ liệu đ ợc gắn với hàm thành vùng riêng mà hàm tác động lên cấm hàm bên truy nhập tới cách tuỳ tiện
- LTHTĐ cho phép phân tích tốn thành thực thể gọi đối tợng sau xây dựng liêụ hàm xung quanh đối tợng
- LTHTĐ có đặc tính chủ yếu sau:
1 Tập trung vào liệu thay cho hàm. 2 Chơng trình đợc chia thành đối tợng
3 Các cấu trúc liệu đợc thiết kế sau cho đặc tả đợc đối tợng.
4 Các hàm thao tác vùng liệu đối tợng đợc gắn với cấu trúc dữ liệu đó.
5 Dữ liệu đợc đóng gói lại, đợc che dấu khơng cho phép hàm đợc truy nhập tự do.
6 Các đối tợng tác động trao đổi thông tin với qua hàm.
Con ng êi Tªn? Cha? Mẹ? Anh em?
Con cái? Vợ/chồng?
Sinh C ới Là anh Là ông nội
(6)7 Có thể dễ dàng bổ sung liệu hàm vào đối tợng cần thiết.
Mét sè kh¸i niƯm lËp trình HĐT 3.1 Đối tợng (Object)
- i tng kết hợp liệu thủ tục (hay gọi phơng thức-method) thao tác liệu Có thể đa cơng thức phản ánh chất kỹ thuật lập trình hớng đối tợng nh sau:
Đối tợng = Dữ liêu + Phơng thøc 3.2 Líp (Class)
- Lớp khái niệm LTHTĐ Đó tập đối tợng có cấu trúc liệu phơng thức giống (hay nói cách khác tập đối tợng loại) Nh có lớp biết đợc mơ tả cấu trúc liệu phơng thức đối t-ợng thuộc lớp Mỗi đối tt-ợng thể cụ thể lớp Trong lập trình, coi lớp nh kiểu, đối tợng biến có kiểu lớp
3.3 Nguyên tắc đóng gói
- Trong LTCT ta thấy hàm hay thủ tục đợc sử dụng mà không cần biết đến nội dung cụ thể Ngời sử dụng cần biết chức hàm nh tham số cần truyền để gọi hàm chạy mà không cần quan tâm đến lệnh cụ thể bên Ngời ta gọi đóng gói chức
- Trong LTHTĐ khơng chức đợc đóng gói mà liệu đợc đóng gói Với đối tợng, ta truy nhập trực tiếp vào thành phần liệu mà phải thông qua thành phần chức (các phơng thức) để làm việc
- Chúng ta thấy đóng gói thực liệu có ngôn ngữ LTHTĐ “thuần khiết-pure” theo nghĩa ngôn ngữ đợc thiết kế từ đầu cho LTHTĐ Đối với ngôn ngữ “lai-hybrid” đợc xây dựng ngôn ngữ khác ban đầu cha phải hớng đối tợng nh C++ có ngoại lệ định vi phạm nguyên tắc đóng gói liệu
3.4 TÝnh kÕ thõa (inheritance)
- Một khái niêm quan trọng LTHTĐ kế thừa Sự kế thừa cho phép định nghĩa lớp sở lớp tồn tại, tất nhiên có bổ sung ph ơng thức hay thành phần liệu Khả kế thừa cho phép sử dụng lại cách dễ dàng modul chơng trình mà khơng cần thay đổi modul Rõ ràng điểm mạnh LTHTĐ so với LTCT
Ví dụ: Xét toán
Để quản lý việc thu học phí phát học bổng sinh viên khoa gồm hệ: Hệ s phạm, hệ cử nhân, hệcử nhân chức, ngời ta quản lý theo thuộc tính sau:
- Hệ s phạm: Lớp học, họ tên, ngày sinh, häc kú, §TB, møc häc bỉng
- HƯ cư nhân: Lớp học, họ tên, ngày sinh, học kỳ, §TB, møc häc bỉng, møc häc phÝ - HƯ t¹i chức: Lớp học, họ tên, ngày sinh, học kỳ, mức học phí
HÃy xây dựng chơng trình cho phép:
- Cuối học kỳ, ngời quản lý sinh viên nhập vào thông tin cho hệ
(7)- Tính tổng học phí phải thu lớp học kỳ(đối với hệ CN hệ TC)
- In danh sách phát học bổng cho lớp (đối với hệ SP hệ CN) danh sách thu học phí lớp (đối với hệ CN hệ TC)
Thông thờng để giải toán ngời ta thờng tạo cấu trúc liệu tơng ứng với hệ Trên cấu trúc liệu ngời ta phải viết hàm nhập liệu, hàm in liệu Ngời ta phải viết hai hàm tính tổng học bổng cho hệ SP hệ CN, viết hai hàm tính tổng học phí cho hai hệ CN hệ chức
Rõ ràng với cách phân tích lập trình trên, ta phân tích cấu trúc liệu cách độc lập, khơng có liên hệ với Nhng thực tế, sinh viên đợc quản lý số thuộc tính nh nhau: Lớp học, họ tên, ngày sinh, học kỳ sau hệ đợc bổ sung thêm số thuộc tính Do ta sử dụng tính kế thừa lại nh sau mơ hình sau
Khi sử dụng mơ hình kế thừa ta dễ dàng sử dụng lại hàm có mà khơng cần viết lại hàm Điều quan trọng bổ sung thay đổi thuộc tính, hàm lớp sở thuộc tính hay hàm tự động thay đổi
KÕ thõa KÕ thõa
KÕ thõa KÕ thõa
SVCN - NhËp d÷ liƯu - In d÷ liƯu
- TÝnh tỉng häc bỉng - TÝnh tỉng häc phÝ SVSP
- §TB - Häc bỉng - NhËp d÷ liƯu - In d÷ liƯu
- TÝnh tỉng häc bỉng
SVTC - Häc phÝ - NhËp d÷ liƯu - In d÷ liƯu
- TÝnh tỉng häc phÝ SV
Líp - Họ tên - Ngày sinh - Học kỳ
(8)lớp kế thừa mà không cần thay đổi lớp kế thừa Chính điều làm cho chơng trình lập trình theo hớng đối tợng dễ dàng bảo trì lập trỡnh cu trỳc
3.5 Tính đa hình (polymorphime)
(9)Chơng Một số đặc điểm mở rộng C++
2.1.To¸n tư xt, nhËp
Trong C++ cung cấp toán tử xuất, nhập thuận lợi toán tử Để sử dụng cần khai báo thêm vào chơng trình tệp <iostream.h>
2.1.1 Toán tử xuÊt (<<) VÝ dô:
#include <iostream.h> #include <conio.h> void main(){
char *st="Welcome C++"; cout << st;
cout << "\n"; int i=5;
cout <<"Gia tri cua i ="<< i<<"\n"; float f=3.14;
cout <<"Gia tri cua f ="<< f<<"\n"; getch();
}
Tốn tử “<<” tốn tử hai ngơi, tốn hạng bên trái mô tả nơi kết xuất thông tin (có thể thiết bị ngoại vi chuẩn hay tập tin), toán hạng bên phải biểu thức Cách kết xuất có lợi ngời lập trình khơng phải nhớ định dạng cho kiểu liệu khác nh đa hàm printf Chơng trình biên dịch tự động nhận biết kiểu liệu truyền đa hình theo kiểu tơng ứng
2.1.2 To¸n tư nhËp (>>)
Ngợc lại toán tử xuất toán tử nhập >> Toán tử cho phép nhập liệu cho biến kiểu char, int, float, double, và char *.
VÝ dô:
#include <iostream.h> #include <conio.h> void main(){
char *st;
cout <<"Nhap xau :" ; cin >> st;
int i;
cout <<"Nhap gia tri cho i ="; cin >> i;
float f;
cout <<"Nhap gia tri cho f ="; cin >>f;
cout <<"Xau la :"<<st<<"\n";
(10)}
Ví dụ: Lập chơng trình nhập vào mảng hai chiều n dịng, m cột In hình dạng ma trận nhập ma trận chuyển vị
2.2.To¸n tư ph¹m vi (::)
Khi có định nghĩa trùng tên biến cục biến tổng thể, có truy xuất qua tên biến trình biên dịch hiểu truy xuất biến cục Để truy xuất biến tổng thể phải dùng tốn tử phạm vi
VÝ dô:
#include <iostream.h> #include <conio.h> int i=5;
void main(){ int i=1; clrscr();
cout <<"Gia tri cua bien cuc bo i="<<i<<"\n"; cout <<"Gia tri cua bien tong the i="<<::i<<"\n"; getch();
}
2.3 BiÕn tham chiÕu (reference)
Trong C++ đa khái niệm biến tham chiếu Biến tham chiếu bí danh (alias) đối tợng Một biến tham chiếu dùng để tham chiếu tới biến kiểu liệu nhớ, tức chứa địa biến nhớ Các phép toán thao tác biến tham chiếu thực chất thao tác biến nhớ mà tham chiếu đến Để khai báo biến tham chiếu ta sử dụng kí tự & sau kiểu liệu
int i=5;
//Khai b¸o biÕn tham chiÕu kiĨu int, tham chiÕu tíi i
int &r=i;
//Truy nhËp i th«ng qua biÕn tham chiÕu r
r++; // thay đổi i ->i=6
Nh vËy mét biÕn tham chiÕu thùc chÊt gièng víi trá nhng nã có số điểm khác biệt:
+ Khi khai báo biến tham chiếu luôn phải xác lập biến mà tham chiếu đến, khơng có tham chiếu đến địa null (con trỏ có)
VÝ dô:
int n=3, m=10; int *p;
p=&n;// p tr n n
*p=m;// gán giá trị m cho n th«ng qua trá p
int &q;// sai q phải đợc khởi tạo
int &q=n;// khai báo tham chiếu q đến n
(11)q=m;// gán giá trị biến m cho biÕn n.
+ Khơng có tham biến đến kiểu void nhng trỏ lại có trỏ đến kiểu void 2.3.1.Truyển tham số cho hàm tham chiếu
- Biến tham chiếu thực chất kiểu liệu nên truyền nh đối số hàm Việc dùng khái niệm tham chiếu khai báo tham số hình thức hàm yêu cầu chơng trình dịch truyền địa biến cho hàm va hàm thao tác trực tiếp biến
Xét ví dụ hốn đổi giá trị hai biến : #include <iostream.h> #include <conio.h>
//Ham swap1() thuc hien viec truyen tham so bang tham tri void swap1(int x, int y){
int temp=x; x=y; y=temp; }
//Ham swap2() thuc hien viec truyen tham so bang tro void swap2(int *x, int *y){
int temp=*x; *x=*y; *y=temp; }
//Ham swap3() thuc hien viec truyen tham so bang tham chieu void swap3(int &x, int &y){
int temp=x; x=y; y=temp; }
void main(){ int a=3, b=5; swap1(a,b);
cout<<"a="<<a<<" va b =" <<b<<"\n"; a=3;b=5;
swap2(&a,&b);
cout<<"a="<<a<<" va b =" <<b<<"\n"; a=3;b=5;
swap3(a,b);
cout<<"a="<<a<<" va b =" <<b<<"\n"; getch();
}
(12)- Giải pháp đa hàm swap2() thay truyền trực tiếp giá trị hai biến a b ta truyền địa chúng thông qua địa để xác định giá trị biến Bằng cách giá trị hai biến a b hoán đổi cho sau lời gọi hàm
- Hàm swap3() đa giải pháp sử dụng tham chiếu Các tham số hình thức hàm swap3() tham chiếu đến tham số thực đợc truyền cho hàm giá trị hai tham số thực a b hốn đổi đợc cho
Chú ý truyền số cho hàm khai báo biến tham chiếu số khơng thể lấy đợc địa tham chiếu Ví dụ: swap3(3,4) sai
2.3.2.Hàm trả tham chiếu Định nghĩa hàm có dạng sau: <type> & tên hàm (các tham số){
return <biến có phạm vi toàn cục>; }
VÝ dô:
#include <iostream.h> #include <conio.h> int a=0, b=0;
//ham tra ve mot tham chieu toi kieu int int &Thambien(int i){
return (i) ? a:b; }
void main(){
Thambien(0)=5; //Ham tra ve tham chieu den b ->b=5; Thambien(1)=4; //Ham tra ve tham chieu den a ->a=4; cout <<"a,b ="<<a<<","<<b;
getch(); }
- Hàm Thambien() trả tham chiếu đến biến tổng thể nên sử dụng kết trả để gán giá trị cho biến tổng thể Khi viết hàm trả tham chiếu ý không đợc trả tham chiếu tới mọt biến cục hàm kết thúc hàm tồn biến cục bị huỷ khỏi stack nh khơng cịn nhớ Nếu hàm trả tham chiếu đến biến cục sử dụng trả tham chiếu đến biến khơng cịn nhớ gây tợng treo máy
2.4.Tham số ngầm định lời gọi hàm
- Đối với hàm đợc định nghĩa tham số ngầm định, sử dụng hàm gọi hàm mà khuyết tham số ngầm định Khi tham số đợc lấy giá trị truyền vào theo tham số ngầm định
VÝ dơ: LËp ch¬ng trình viết hàm tính diện tích chu vi hình chữ nhật #include <iostream.h>
(13)//Ham khai bao voi tham so ngam dinh float chuvi(float a=0,float b=0){
return 2*(a+b); }
//Ham khai bao binh thuong
float dientich(float a,float b){ return a*b;
}
void main(){
cout<<”\n Chu vi:”<<chuvi(); // Dung
cout<<”\n Chu vi:”<<chuvi(10); // Dung cout<<”\n Chu vi:”<<chuvi(10,10); // Dung
cout<<”\n Dien tich:”<<dientich(); // Sai
cout<<”\n Dien tich:”<<dientich(10,10); //Dung getch();
}
Chó ý:
1 Các tham số với giá trị ngầm định phải đợc đặt cuối danh sách tham số hàm, tức thứ tự ngầm định phải tuân theo từ phải sang trái Khi đối số phía sau khơng có ngầm định tham số phía trớc khơng đợc ngầm định
void fct(int x = 0, int y = 0); // Dung void fct(int x = 0, int); // Sai
void fct(int, int y =0 ); // Dung 2 Các giá trị ngầm định biểu thức bất kỳ.
VÝ dô:
float x = 2; int n = 3;
void fct(float y = 2*n+1.5*x);
2.5 Định nghĩa hàm inline
Khi có lời gọi hàm đợc thực chơng trình phải có số thao tác chuẩn bị nh tạo liệu cục tham số truyền vào stack, lu địa trở Khi kết thúc hàm phải huỷ liệu cục khỏi stack Nh chơng trình phí thời gian để làm công việc chuẩn bị cho việc gọi hàm Khi có hàm đơn giản số dịng lệnh dễ thấy công việc chuẩn bị tốn thời gian thân thực ch -ơng trình Để tránh trờng hợp ngời ta đa khái niệm hàm inline Hàm inline loại hàm giả có nghĩa có lời gọi hàm đâu chơng trình thêm trực tiếp đoạn mã lệnh hàm vào mà khơng gọi hàm riêng biệt nh bình thờng Để định nghĩa hàm inline việc thêm từ khố inline lên đầu
VÝ dơ:
#include <iostream.h> #include <conio.h>
(14)return (a>b) ? a:b; }
void main(){ int m;
m=max(3,7);//Goi ham inline cout <<m;
getch(); }
Điểm bất lợi dùng hàm inline chúng lớn đợc gọi thờng xun kích thớc chơng trình tăng lên nhanh Vì lý này, hàm đơn giản, không chứa cấu trúc lặp nờn s dng hm inline
2.6 Định nghĩa chồng hµm (Overloading functions)
- Bình thờng hai hàm khác phải định nghĩa với hai tên khác Điều gây bất tiện có hàm có ý nghĩa nhng phải định nghĩa hai tên khác Ví dụ hàm tính max hai số nguyên hai số thực Trong C++ cho phép sử dụng tên cho nhiều hàm khác ta gọi “chồng hàm” Khi gọi hàm với tên này, trình biên dịch dựa đối số truyền vào mà xác định hàm đợc gọi
VÝ dô:
#include <iostream.h> #include <conio.h> int max(int a, int b){ return (a>b) ? a:b; }
double max(double a, double b){ return (a>b) ? a:b;
}
void main(){ int a=5, b=6;
double x=7.5, y=20.2;
cout <<max(a,b)<<"\n"; //Goi max(int, int)
cout <<max(x,y)<<"\n"; //Goi max(double, double) getch();
}
2.7.Định nghĩa chồng toán tử
Cho cấu trúc phân số nh sau:
struct PS { int ts, ms; };
Đây cấu trúc liệu toán học nên có phép tốn +, -, *, /, đảo dấu, Thơng th-ờng để xây dựng phép tốn ta phải viết hàm:
PS cong(PS x, PS y){ PS temp;
(15)temp.ms = x.ms*y.ms; return temp;
}
PS tru(PS x, PS y){ PS temp;
temp.ts = x.ts*y.ms - x.ms*y.ts; temp.ms = x.ms*y.ms;
return temp; }
PS daodau(PS x){ PS temp;
temp.ts = - x.ts; temp.ms = x.ms; return temp; }
PS nhan(PS x, PS y){ PS temp;
temp.ts = x.ts*y.ts; temp.ms = x.ms*y.ms; return temp;
}
Giả sử cần tính giá trị biểu thức: s1 = -a + b - c;
s2 = -a * b + c*d - e;
Víi a, b, c, d, e phân số ta ph¶i viÕt: s1 = cong(daodau(a),tru(b,c));
s2 = cong(nhan(daodau(a),b),tru(nhan(c,d),c)); Chó ý cách biểu diễn không
Rõ ràng cách gọi nh không trực quan cách viết trực tiếp công thức lập trình Hơn ta có biểu thức phức tạp nh, viết lời gọi hàm nh cộng, trừ, đảo dấu phức tạp Để khắc phục điều C++ định nghĩa chồng toán t
Định nghĩa chồng toán tử cộng cho phân sè: PS operator +(PS x, PS y){
PS temp;
temp.ts = x.ts*y.ms + x.ms*y.ts; temp.ms = x.ms*y.ms;
return temp; }
PS operator -(PS x, PS y){ PS temp;
(16)temp.ms = x.ms*y.ms; return temp;
}
PS operator -(PS x){ PS temp;
temp.ts = - x.ts; temp.ms = x.ms; return temp; }
PS operator *(PS x, PS y){ PS temp;
temp.ts = x.ts*y.ts; temp.ms = x.ms*y.ms; return temp;
}
Thực chất việc định nghĩa toán tử giống định nghĩa hàm với tên khác biệt có từ khoá operator toán tử kèm theo Sau định nghĩa hàm theo kiểu đặc biệt gọi kiểu toán tử nh sau:
PS a,b,c;
c = a+b; // thùc chÊt lµ lêi gäi hµm c = operator + (a,b) c = a-b; // thùc chÊt lµ lêi gäi hµm c = operator - (a,b) c = -a; //thùc chÊt lµ lêi gäi hµm c = operator - (a)
c = -a+b-c; //gäi c¸c hàm operator theo thứ tự toán tử biểu thøc
Chú ý: Hầu hết toán tử C++ đợc định nghĩa chồng Tuy nhiên có một số tốn tử khơng đợc định nghĩa chồng là: , *, :: ?:
2.8.To¸n tư new vµ delete
2.8.1.Tốn tử cấp phát nhớ động new
- Với khai báo: int *adr; lệnh adr=new int; cho phép cấp phát vùng nhớ cần thiết cho phần tử có kiểu int gán cho adr địa tơng ứng Lệnh tơng ứng C là: adr=(int*) malloc(sizeof(int));
- Với khai báo: char *adc lệnh adc=new char[100] cho phép cấp phát vùng nhớ đủ cho mảng 100 ký tự đặt địa đầu vùng nhớ cho biến adc Lệnh tơng ứng C là: adc=(char *) malloc(100)
D¹ng lƯnh: Cã hai d¹ng D¹ng 1: new type
Trả giá trị trỏ đến vị trí tơng ứng cấp phát nhớ thành công, ngợc lại trả giá trị NULL
D¹ng 2: new type[n]
(17)2.8.2.Tốn tử giải phóng vùng nhớ động
Một vùng nhớ động đợc cấp phát new phải đợc giải phóng delete mà khơng thể dùng free
VÝ dô: delete adr; delete adc;
Ví dụ: Lập chơng trình nhập in phần tử mảng hai chiều việc cấp phát nhớ động
#define N #define M
#include <iostream.h> #include <conio.h> void nhap(int **a); void inra(int **a); void main(){
int **a; int i;
//Cap phat mang N tro nguyen a=new int*[N];
for (i=0;i<N;i++)
//Moi tro nguyen xac dinh vung nho cho M so nguyen a[i]=new int[M];
//Nhap so lieu
cout <<"Nhap so lieu cho ma tran \n"; nhap(a);
//In mang
cout<<"\n Ma tran vua nhap \n"; inra(a);
// Giai phong bo nho for (i=0;i<N;i++) delete a[i];
delete a; getch(); }
/* -*/ void nhap(int **a){
for (int i=0;i<N;i++) for (int j=0;j<M;j++){
cout<<"A["<<i<<","<<j<<"]="; cin>>a[i][j];
} }
/* -*/ void inra(int **a){
(18)for (int j=0;j<M;j++) cout<<a[i][j]<<" "; cout<<"\n";
(19)Chơng đối tợng lớp (object & class) 3.1 Đối tợng (Object)
Một đối tợng đóng gói liệu (thuộc tính) thao tác (phơng thức) trên Mỗi đối tợng có thuộc tính phơng thức riêng ca mỡnh.
Đối tợng = Dữ liệu + Phơng thức
Chú ý: Trong C++ phơng thức các hàm.
Vớ d: Mt mụ t v cỏc đối tợng điểm trên mặt phẳng nh sau:
- Mỗi đối tợng đợc xác định hai thành phần toạ độ (x,y)
- Các thao tác tác động lên điểm bao gồm: + Hàm đặt toạ độ điểm vị trí (ox, oy)
+ Hàm tịnh tiến điểm có toạ độ (x,y) đến điểm có toạ độ x+dx, y+dy.
+ Hàm hiển thị toạ độ điểm. Đối tợng điểm đợc mô tả nh sau:
Mô tả đối tợng điểm{
// Dữ liệu - mô tả toạ độ điểm float x, y;
(20)void init (float ox, float oy){ x = ox;
y = oy; }
void move(float dx, float dy){ x = x+dx;
y = y+dy; }
void display(){
cout<<"\n x="<<x<<" y ="<<y<<endl; }
Một mô tả chung cho đối tợng loại gọi lớp Ví dụ mơ tả chung cho đối t-ợng điểm mặt phẳng lớp ta lấy tên lớp point Trong lớp ngời ta đa ra các mơ tả tính chất thành phần liệu, cách thức thao tác thành phần này Ví dụ mơ tả lớp point gồm hai phần, phần thứ thuộc tính gồm có hai toạ độ xác định điểm mặt phẳng, phần thứ hai phơng thức tác động lên điểm
Nh nói lớp mơ tả tổng quát đối tợng loại đối tợng là thể cụ thể lớp
3.2 Líp (Class) 3.2.1.Khai b¸o líp
Trong C++ lớp đợc định nghĩa giống nh cấu trúc nhng có thêm thành phần hàm Hàm thành phần lớp khai báo giống nh hàm bình thờng nhng đợc đặt lớp Nói chung cú pháp khái báo lớp điển hình là:
class <tªn líp> { private:
<Khai báo định nghĩa thành phần riêng đối tợng> public:
<Khai báo định nghĩa thành phần công cộng đối tợng> };
<Định nghĩa hàm thành phần cha đợc định nghĩa bên khai báo lớp>
Trong khai báo này:
- Tờn lp l tên ngời lập trình tự đặt, tuân theo quy tắc đặt tên biến - Thành phần đợc hiểu liệu phơng thức (hàm)
- Khai b¸o:
+ Đối với biến: Khai báo giống nh khai báo biến + Đối với hàm: Khai báo hàm nguyên mẫu - Định nghĩa: Là khai báo viết néi dung cđa hµm
(21)- Tất hàm định nghĩa bên lớp hàm inline hàm có cấu trúc lặp khơng nên định nghĩa định nghĩa lớp
VÝ dơ 3.1: Minh ho¹ líp point #include <iostream.h> #include <conio.h> class point{
//Khai bao cac phan du lieu rieng
private:
float x, y;
//Khai bao cac ham phan cong cong
public:
//Khai bao va dinh nghia ham phan khai bao lop
void init(float ox, float oy){ x=ox;
y=oy; }
//Khai bao ham lop nhung chua dinh nghia
void move(float dx, float dy); void display();
};
//D/n cac ham phan chua duoc d/n ben khai bao lop
/* -*/
void point::move(float dx, float dy){ x+=dx;
y+=dy; }
/* -*/
void point::display(){
cout<<"x="<<x<<", y="<<y<< "\n"; }
/* -*/ void main(){
(22)point p;
p.init(2,4); p.display(); p.move(1,2); p.display(); getch();
}
a Tạo đối tợng
Một đối tợng đợc xác lập thông qua biến/hằng có kiểu lớp <Tên lớp> <tên đối tợng>;
Mỗi đối tợng sở hữu tập biến tơng ứng với tên kiểu thành phần liệu định nghĩa lớp Lớp kiểu liệu khai báo trỏ hay tham chiếu đến đối tợng thuộc lớp cách truy nhập gián tiếp đến đối t-ợng Nhng ý trỏ tham chiếu thể lớp
Ví dụ:
Khai báo: point p, q;
Đối tợng p Đối tợng q
Thành phần liệu p - x,y
Thành phần liệu q - x,y
Các phơng thức p - init()
- move() - display()
Các phơng thức cña q - init()
- move() - display() b Các thành phần liệu
Cú pháp khai báo thành phần liệu giống nh khai báo biến: <Tên kiểu> <tên thành phần>;
Thnh phn d liu lớp kiểu liệu chuẩn (int, float, double, char, char*), kiểu cấu trúc lớp khác Một lớp sau định nghĩa coi nh cấu trúc liệu mà có thêm hàm xử lý sử dụng nh cấu trúc
class A { };
(23)A a; };
c.Các hàm thành phần
- Hm đợc khai báo định nghĩa lớp đợc gọi hàm thành phần hay phơng thức lớp (hàm thành phần thuật ngữ C++, phơng thức thuật ngữ lập trình hớng đối tợng nói chung) Các hàm thành phần truy nhập đến thành phần liệu hàm thành phần khác lóp Nh lần thấy đợc phơng thức thao tác xử lý liệu đối tợng
- Định nghĩa hàm thành phần đặt bên hay bên lớp, định nghĩa hàm thành phần đặt khai báo lớp (đó hàm inline) khơng có khác so với định nghĩa hàm thông thờng
- Khi định nghĩa hàm thành phần lớp, cú pháp định nghĩa là:
<Tên kiểu giá trị hàm> <tên lớp>::<tên hàm>(<danh sách tham số>){ <Nội dung hàm>
}
Đây cách phân biệt hàm thành phần với hàm tự do, điều cho phép hai lớp khác có hàm thành phần cïng tªn
- Cũng định nghĩa hàm thành phần tệp khai báo lớp tệp khác
- Gọi hàm thành phần lớp từ đối tợng truyền liệu cho hàm thành phần
Có ph¸p:
<Tên đối tợng>.<tên hàm thành phần>(<danh sách tham số>) Ví dụ 3.2. Định nghĩa lớp tệp tiêu đề
Tạo tệp tiêu đề: mypoint.h #include <iostream.h> class point{
//Khai bao cac phan du lieu rieng private:
float x, y;
//Khai bao cac ham phan cong cong public:
void init(float ox,float oy); //ham thiet lap void move(float dx,float dy);
void display(); };
Chú ý: Tên lớp không cần trùng tên với tệp tiêu đề Tệp chơng trình:
//Mo tep tieu de
(24)//D/n cac ham phan chua duoc d/n ben khai bao lop void point::init(float ox,float oy){
x=ox;y=oy; }
void point::move(float dx,float dy){ x+=dx;y+=dy;
}
void point::display(){
cout<<"x="<<x<<" y="<<y<<"\n"; }
void main(){ clrscr(); point p; p.init(2,4); p.display(); p.move(1,2); p.display(); getch(); }
d Ph¹m vi líp
Để kiểm soát truy nhập đến thành phần (dữ liệu, hàm) lớp, C++ đ a khái niệm phạm vi lớp Tất thành phần một
lớp đợc coi thuộc phạm vi lớp, tức là trong định nghĩa hàm thành phần của lớp truy nhập đến một thành phần lớp đó.
e.Từ khố xác định quyền truy xuất
- Trong định nghĩa lớp xác định khả truy nhập lớp đến thành phần private public từ khoá xác định quyền truy nhập
- Mọi thành phần đợc liệt kê phần public lớp truy nhập đợc hàm, lớp
- Mọi thành phần liệt kê phần private lớp đợc quyền truy nhập bên phạm vi lớp
(25)một nhãn hết khai báo lớp Nếu thành phần mà khơng có từ khố xác định quyền truy xuất lấy giá trị ngầm định private cho khai báo lớp class public cho khai báo lớp struct
Ví dụ hai khai báo sau tơng đơng:
struct point{ int x, y;
void init(int, int); void move(int, int); void display();
};
class point{
public:
int x, y;
void init(int, int); void move(int, int); void display();
};
3.2.2 Kh¶ hàm thành phần
- Cho phộp định nghĩa chồng hàm thành phần.
- Các tham số với giá trị ngầm định.
- Cho phép sử dụng đối tợng nh tham số của hàm thành phần.
+ Đợc truy nhập đến thành phần private trong đối tợng.
+ Truy nhập đến thành phần private trong tham số đối tợng truyển cho hàm thành phần.
+ Cho phép sử dụng đối tợng làm giá trị trả về.
- Con trỏ this: Từ khóa this định
(26)Nói cách khác, trỏ this tham chiếu đến đối tợng gọi hàm thành phần Nh vậy,
có thể truy nhập đến thành phần của đối tợng gọi hàm thành phần gián
tiÕp thông qua trỏ this.
Ví dụ: Hàm init cđa líp point vÝ dơ trªn cã thĨ viÕt l¹i nh sau:
void point::init(float ox,float oy){ this->x=ox;
this->y=oy; }
Bµi tËp 1
a Xây dựng lớp point gồm thành phần: - Các thuộc tính x, y mơ tả toạ độ điểm
- Hàm init(float ox, float oy) để tạo điểm toạ độ (ox, oy)
- Hàm move(float dx, float dy) để tịnh tiến điểm có đến toạ độ (x+dx, y+dy) - Hàm dislay() để hiển thị toạ độ im
b Xây dựng lớp circle gồm thành phÇn:
- Các thuộc tính mơ tả bán kính tâm đờng tròn (tâm điểm) - Hàm init(point X, float or) để tạo đờng trịn có tâm điểm X bán kính or - Hàm area() để tính diện tích hình trịn
- Hàm move(float ox, float oy) để tịnh tiến đờng tròn đến (x+dx, y+dy)
(27)3.3 Hµm thiêt lập (constructor) và hàm huỷ bỏ (destructor)
3.3.1.Hàm thiÕt lËp
Khi đối tợng đợc tạo ln gọi ngay đến hàm thiết lập cho Hàm loại đợc gọi hàm thiết lập cho đối t-ợng Chức hàm thiết lập khởi tạo giá trị thành phần liệu đối t-ợng, xin cấp phát nhớ cho thành phần liệu động.
Các quy định xây dựng hàm thiết lập
1 Trong định nghĩa lớp hàm thiết lập đợc định nghĩa nh hàm mà có tên hàm trùng với tên lớp.
2 Hàm thiết lập lớp phải có quyền
public.
3 Hàm thiết lập giá trị trả và không cần khai báo void.
VÝ dơ: Trong líp point cã thĨ thay thÕ hµm init() bëi hµm thiÕt lËp nh sau: #include <iostream.h>
#include <conio.h> class point{
private:
float x, y;
(28)point(float ox,float oy){ x=ox;y=oy;
}
public:
point(float ox=0,float oy=0){
x=ox;y=oy; }
void move(float dx,float dy); void display();
};
void point::move(float dx,float dy){ x+=dx;y+=dy;
}
void point::display(){
cout<<"x="<<x<<" y="<<y<<"\n"; }
/* -*/ void main(){
clrscr(); point p(2,4); p.display(); p.move(1,2); p.display(); getch(); }
(29)dạng khai báo đối tợng mà trình biên dịch sẽ gọi đến hàm thiết lập với tham số phù hợp.
VÝ dô: class A{
public:
A(); A(char *); A(char *, int); };
thì khai báo:
A a; - gọi đến hàm thiết lập A() A a(“demo”); - gọi đến hàm thiết lập A(char*)
A a(“demo”,1); - gọi đến hàm thiết lập A(char *, int)
A a(5); - lỗi hàm thiết lËp A(int)
5 Hàm thiết lập đợc khai báo với tham số có giá trị ngầm định.
6 Khi lớp khơng có hàm thiết lập nào đợc định nghĩa trình biên dịch ngầm định lớp sử dụng hàm thiết lập ngầm định Hàm thiết lập không có đối số.
VÝ dơ:
class A {
// Khơng có hàm thiết lập đợc định ngha };
thì khai báo:
(30)3.3.2 Hµm hủ bá
Ngợc lại với hàm thiết lập hàm huỷ bỏ, đợc gọi đến đối tợng đợc huỷ khỏi nhớ.
Một số quy định hàm huỷ bỏ:
1.Tên hàm huỷ bỏ bắt đầu bằng dấu ~ theo sau tên lớp tơng ứng Ví dụ với lớp point thì hàm huỷ bỏ ~point().
2 Hàm huỷ bỏ phải có quyền
public
3 Nói chung hàm huỷ bỏ khơng có tham số, lớp có hàm huỷ bỏ (trong có nhiều hàm thiết lập).
(31)sinh hàm huỷ bỏ ngầm định, hàm khơng làm ngồi việc “lấp chổ trống” Đối với các lớp khơng có khai báo thành phần nhớ động, dùng hàm huỷ bỏ ngầm định Ngợc lại, phải khai báo hàm huỷ bỏ để đảm bảo quản lý tốt cho việc giải phóng bộ nhớ động đối tợng chiếm dữ chúng hết thời gian làm việc.
5 Gièng nh hµm thiÕt lËp, hµm hủ bá giá trị trả về.
3.4 Hàm thiÕt lËp chÐp (Copy constructor)
(32)thiết lập chép có chức tạo ra đối tợng chép nội dung từ một đối tợng có sang đối tợng tạo ra. Hàm thiết lập chép có đối số tham chiếu đến đối tợng cùng lớp Ví dụ: Hàm thiết lập chép của lớp point đợc viết nh sau:
point(point &tents) hc
point(const point &tents);
trong từ khố const khai báo tham số hình thức nhằm ngăn cấm thay đổi nội dung tham số truyền cho hàm
- Giống nh hàm thiết lập ngầm định, không định nghĩa hàm thiết lập chép lớp ch-ơng trình dịch tạo hàm thiết lập chép ngầm định nhằm đảm bảo tính đắn ch-ơng trình tình cần đến hàm thiết lập chép Nh vậy, khai báo lớp có hai hàm thiết lập ngầm định hàm thiết lập ngầm định hàm thiết lập chép ngầm định.
- Trong đa số lớp, không dùng thành phần liệu trỏ tham chiếu sử dụng hàm thiết lập chép ngầm định đủ.
3.5 Phép gán đối tợng
(33)VÝ dô:
point a, b; a.init(5,3); b=a;
Thực chất việc chép giá trị thành phần liệu (x,y) từ đối tợng a sang đối tợng b tơng ứng đôi
- Trong trờng hợp lớp có thành phần liệu động, phép gán đối tợng không sao chép liệu liên quan đến vùng liệu động đó, phải định nghĩa phép gán (để hiểu rõ hơn, xem ví dụ tốn tử gán lớp vector phần cuối ch-ơng này).
- Có vẽ lạ lớp có hàm thiết lập chép tốn tử gán, hai chép thành phần liệu đối tợng sang đối tợng khác Sự khác chỗ hàm thiết lập chép có tạo đối tợng cịn tốn tử gán thay đối giá trị đối tợng có
Ví dụ: Lớp mảng động minh hoạ hàm thiết lập, hàm huỷ bỏ, hàm thiết lập chép #include <iostream.h>
#include <stdio.h> #include <conio.h> class vector{
int n; //So phan tu float *v;
public:
vector(); //Ham thiet lap khong tham so vector(int size); //Ham thiet lap tham so vector(int size, float *a); //Ham thiet lap tham so vector(vector &); //Ham thiet lap chep
~vector(){delete v;} //Ham huy bo
void display(); };
/* -*/ vector::vector(){
cout<<"So phan tu :";cin>>n; v=new float[n];
for (int i=0;i<n;i++){ cout<<"v["<<i<<"]="; cin>>v[i];
} }
/* -*/ vector::vector(int size){
n=size;
v=new float[n];
(34)cin>>v[i]; }
}
/* -*/ vector::vector(int size,float *a){
n=size;
v=new float[n];
for (int i=0;i<n;i++) v[i]=a[i];
}
/* -*/ vector::vector(vector &b){
delete v; n=b.n;
v=new float[n];
for (int i=0;i<n;i++) v[i]=b.v[i];
}
/* -*/ void vector::display(){
for (int i=0;i<n;i++) cout<<v[i]<<" "; cout<<"\n";
}
/* -*/ void main(){
clrscr();
vector s1; //Goi ham thiet lap khong tham so s1.display();
vector s2(4);//Goi ham thiet lap tham so s2.display();
float a[5]={1,2,3,4,5}; vector s3(5,a);
s3.display();
vector s4(s1); //Ham thiet lap chep s4.display();
getch(); }
Bµi tËp 2
a Xây dựng lớp point gồm thành phần: - Các thuộc tính x, y mơ tả toạ độ điểm
(35)- Hàm move(float dx, float dy) để tịnh tiến điểm có đến toạ độ (x+dx, y+dy) - Hàm dislay() để hiển thị toạ độ điểm
b X©y dùng líp circle gồm thành phần:
- Cỏc thuc tớnh mụ tả bán kính tâm đờng trịn (tâm điểm)
- Hàm thiết lập với hai tham số tâm bán kính lấy giá trị ngầm định tâm (0,0) bán kính
- Hµm thiÕt lËp chÐp
- Hàm area() để tính diện tích hình trịn
- Hàm move(float ox, float oy) để tịnh tiến đờng tròn đến (x+dx, y+dy)
- Hàm display() để hiển thị toạ độ tâm, bán kính diện tích hình trịn c Viết chơng trình tạo đờng trịn có tâm (x,y) bán kính r (x,y r nhập vào từ bàn phím) Tịnh tiến đờng trịn đến điểm (2*x,3+y), hiển thị toạ độ tâm, bán kính diện tích hình trũn
3.6 Các thành phần tĩnh 3.6.1.Thành phần liƯu tÜnh
Thơng thờng chơng trình đối tợng thuộc lớp sở hữu thành phần liệu riêng Ví dụ xét lớp A:
class A{ int n; float x;
};
víi khai b¸o: point a,b;
sẽ tạo hai đối tợng a,b sở hữu riêng hai vùng liệu khác nh sau:
Tuy nhiên C++ cho phép nhiều đối tợng chia liệu cách đặt từ khoá static trớc khai báo thành phần liệu tơng ứng Ví dụ, ta định nghĩa lớp A nh sau:
class A{
static int n; float x;
};
thì khai báo: A a, b; tạo hai đối tợng có chung thành phần n a.n
a.x
b.n
b.x
object a object b
a.n
a.x b.x
(36)3.6.2.Khởi tạo thành phần liệu tĩnh
- Không thể khởi tạo thành phần liệu static hàm thiÕt lËp cđa mét líp hay khëi t¹o khai b¸o VÝ dơ:
class A{
static int n=0;//Sai float x;
};
- Một thành phần liệu static phải đợc khởi tạo bên lớp Ví dụ: int A::n=0;
Chó ý r»ng thµnh phần liệu tĩnh private pubic.
3.6.3.Các hàm thành phần tĩnh
- Mt hm thành phần đợc khai báo bắt đầu với từ khoá static đợc gọi hàm thành phần tĩnh, hàm thành phần tĩnh độc lập với đối tợng lớp Các hàm thành phần tĩnh lớp đợc gọi theo cú pháp sau:
<tªn líp>::<tªn hàm thành phần tĩnh> (<các tham số có>)
Tất nhiên gọi hàm thành phần tĩnh thông qua đối tợng
- Thông thờng hàm thành phần tĩnh đợc dùng để xử lý chung tất đối tợng lớp, chẳng hạn để hiển thị thông tin liên quan đến cỏc thnh phn d liu tnh
3.7 Hàm bạn lớp bạn
Mt lp cú th cho phộp hàm lớp khác truy xuất tới biến private Sự truy xuất nh phải đợc ghi rõ cách khai báo hàm lớp khác friend (bạn) Những hàm lớp friend đợc xử lý nh thành phần lớp xét, có khả truy xuất không hạn chế đến biến private i tng
3.7.1.Hàm tự bạn lớp Ví dụ: Hàm tự bạn lớp
a Xây dựng lớp point gồm thành phần sau: - Thuộc tính x,y mơ tả toạ độ điểm
- Hàm thiết lập với hai tham số lấy giá trị ngầm định - Hàm thiết lập chép
- Hàm hiển thị toạ độ điểm
- Khai báo hàm tự có tên distance(point A, point B) để tính khoảng hai điểm
b Xây dựng lớp line gồm thành phần sau: - Hai điểm xác định đoạn thẳng
- Hµm thiÕt lËp víi hai tham số hai điểm - Hàm hiển thị khoảng cách hai điểm
c Viết hàm tự tính khoảng cách hai điểm
(37)#include<iostream.h> #include<conio.h> #include<math.h>
//Xay dung lop point
class point{ private:
float x,y; public:
point(float ox=0, float oy=0){ x=ox;y=oy;
}
point(point &p){ x=p.x;y=p.y; }
void display(){
cout<<"\n x="<<x<<"y="<<y; }
friend float distance(point A, point B); };
/* -*/
//Xay dung lop line
class line{ private: point A,B; public:
line(point X, point Y){ A=X;B=Y;
}
void display(){
cout<<"\n Khoang cach:"<<distance(A,B); }
};
/* -*/
//Viet ham tu tinh khoang cach
float distance(point A, point B){
return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2)); }
(38)clrscr();
float x1,y1,x2,y2;
cout<<"Toa diem A:"; cin>>x1>>y1; cout<<"Toa diem B:"; cin>>x2>>y2; point A(x1,y1), B(x2,y2);
line l(A,B); l.display(); getch();
}
Ví dụ: Định nghĩa toán tử lớp #include <iostream.h> #include <conio.h> class integer{ private: int value; public:
integer(int i=0){value=i;} integer operator +(integer i){
return value+i.value; }
void display(){
cout<<value<<"\n"; }
};
void main(){ integer i1=10;
integer i2=i1+5; //Dung vi thuc chat i2 = i1.operator+(5) integer i3=3+i2; //Sai vi khong the i3 = 3.operator+(i2) getch();
}
- Trong ví dụ dễ thấy hàm tốn tử hai toán hạng nảy sinh vấn đề chúng thành phần lớp Toán tử +, thành phần lớp integer xử lý biểu thức hai tốn hạng integer, hay toán hạng bên trái integer toán hạng bên phải int Trong trờng hợp này, hàm thiết lập đợc dùng để chuyển int thành integer tạm thời
- Tuy nhiên ví dụ cho thấy điều lại khơng thể đợc toán hạng bên trái int Phơng thức toán tử + phải đợc gắn với đối tợng integer, phải tốn hạng bên trái Nói cách khác, việc chuyển kiểu tự động hàm thiết lập chuyển kiểu thực cho toán hạng bên phải toán tử có hai tốn hạng, tốn tử thành phần lớp
(39)#include <iostream.h> #include <conio.h> class integer{ private: int value; public:
integer(int i=0){value=i;}
friend integer operator +(integer i1, integer i2); void display(){
cout<<value<<"\n"; }
};
integer operator +(integer i1, integer i2){ return i1.value+i2.value;
}
void main(){ integer i1=10;
integer i2=i1+5; //Dung vi thuc chat la i2 = operator+(i1,5) integer i3=3+i2; //Dung vi thuc chat la i3 = operator+(3,i2) getch();
}
Phiên sau định nghĩa rõ ràng hai toán hạng hàm toán tử +, hàm thiết lập chuyển kiểu làm việc cho hai tốn hạng Chúng ta thấy hầu hết toán tử hai toán hạng cho lớp đợc định nghĩa friend để có đợc khả 3.7.2 Hàm thành phần lớp bạn lớp khác
Có thể xem trờng hợp đặc biệt trờng hợp trên, khác cách mô tả hàm Giả thiết có hai lớp A B, B có hàm thành phần f khai báo nh sau:
int f(char, A);
Nếu f có nhu cầu truy xuất vào thành phần riêng A f cần đợc khai báo bạn lớp A, lớp A cần khai báo:
friend int B::f(char, A);
Tuy nhiên chơng trình dịch cần phải biết khai báo lớp B, nghĩa B phải đợc khai báo trớc lớp A Mặt khác, lớp B lại có khai báo: int f(char, A) điều bắt buộc chơng trình dịch phải biết A lớp (không cần thiết phải biết chi tiết lớp A) Để thực đợc ta cần khai báo: class A; trớc khai báo lớp B Tóm lại sơ đồ khai báo định nghĩa là:
class A;// Khai báo trớc lớp B để A lớp
class B{
(40)};
class A{
friend int B::f(char, A):
};
// Định nghĩa hµm f
int B::f(char, A){
//Néi dung cđa hàm.
}
3.7.3 Hàm bạn nhiều lớp
Về nguyên tắc, hàm (hàm tự hay hàm thành phần) bạn nhiều lớp khác
VÝ dơ: hµm f lµ hµm bạn hai lớp A B class B;
class A{
friend void f(A,B);
};
class B{
friend void f(A,B);
};
void f(A,B){
//Truy nhập vào thành phần riêng hai lớp A B
}
3.7.4 Líp b¹n
Đây trờng hợp tổng quát khai báo lớp bạn bè với hàm lớp khác Giả sử có hai lớp A B, với khai báo:
(41)class A{
friend class B; };
class B{
//Các hàm thành phần lớp B
};
thì tất hàm thành phần lớp B bạn cđa líp A VÝ dơ: Líp b¹n
a Xây dựng lớp point gồm thành phần sau: - Thuộc tính x,y mơ tả toạ độ điểm
- Hàm thiết lập với hai tham số lấy giá trị ngầm định - Hàm thiết lập chép
- Hàm hiển thị toạ độ điểm
- Khai báo lớp line bạn lớp point b Xây dựng lớp line gồm thành phần sau: - Hai điểm xác định đoạn thẳng
- Hµm thiÕt lËp víi hai tham sè lµ hai ®iĨm
- Hàm tính khoảng cách hai điểm xác định đoạn thẳng - Hàm hiển thị khoảng cách hai điểm
c Viết chơng trình nhập vào toạ độ (x1,y1) (x2,y2) hai điểm A, B Tạo đoạn thẳng xác định hai điểm A,B hiển thị khoảng cách hai điểm
#include<iostream.h> #include<conio.h> #include<math.h> class line;
class point{ private:
float x,y; public:
point(float ox=0, float oy=0){
x=ox; y=oy;
}
(42)void display(){
cout<<"\n x="<<x<<"y="<<y; }
friend class line; };
// -class line{
private: point A,B; public:
line(point X, point Y){ A=X;B=Y;}
float distance(){
return sqrt(pow(A.x-B.x,2)+pow(A.y-B.y,2)); }
void display(){
cout<<"\n Khoang cach:"<<distance(); }
};
// -void main(){
clrscr();
float x1,y1,x2,y2;
cout<<"Toa diem A:"; cin>>x1>>y1; cout<<"Toa diem B:"; cin>>x2>>y2; point A(x1,y1) ;
poin B;
b=point(x2,y2) ; line l(A,B);
l.display(); getch();
(43)Chơng Tính kế thừa (inheritance)
4.1.Khái niệm
- Tính kế thừa cho phép định nghĩa lớp lớp có Một lớp kế thừa từ lớp khác đợc gọi lớp dẫn xuất (derived class) Lớp đợc lớp khác kế thừa đợc gọi lớp sở (base class)
- Lớp dẫn xuất kế thừa thành phần (dữ liệu, hàm) lớp sở, đồng thời thêm vào thành phần mới, bao gồm việc làm “tốt hơn” làm lại công việc mà lớp sở cha làm tốt khơng cịn phù hợp với lớp dẫn xuất
- Sù kÕ thõa còng cho phÐp nhiÌu líp cã thĨ dÉn xt tõ cïng mét líp c¬ së, mét líp dÉn xt cịng cã thĨ lớp sở cho lớp khác
4.2.Tớnh k thừa đơn giản Ví dụ 4.1
#include <iostream.h> #include <conio>
class point{ private: float x,y; public:
point(){x=0;y=0};
point(float ox, float oy){x=ox;y=oy;} point(point &p){x=p.x;y=p.y;) void display(){
cout<<”Toa (“<<x<<”,”<<y<<”)”; }
void move(float dx, float dy){ x+=dx;y+=dy;
} };
class coloredpoint:public point{ private:
unsigned int color; public:
coloredpoint():point(){ color=0;
}
coloredpoint(float ox, float oy, unsigned int c):point(ox,oy){
color=c; }
coloredpoint(coloredpoint &b):point((point &)b){ color=b.color;
}
void display(){
point::display();
cout<<”Color=”<<color<<"\n"; }
};
void main(){ clrscr();
coloredpoint m(1,2,3); cout<<”Diem m”;
(44)m.point::display();//Goi display lop point (chi co toa do) m.move(5,4);
m.display();//(x,y,mau)=(5,7,3); m.point::move(6,7);
m.display(); (x,y,mau)=(11,14,3); point p;
p=m; //Hop le–Da dung phep chuyen kieu ngam dinh tu lop dan xuat sang lop CS p.display();
coloredpoint n;
//n=p;//Khong hop le getch();
}
4.2.1.Truy nhËp thành phần lớp sở
- Mt lớp dẫn xuất truy nhập đến thành phần private lớp sở Ví dụ thành phần private x y lớp sở point không đợc truy nhập định nghĩa hàm thành phần lớp dẫn xuất Đây chế kiểm sốt nghiêm ngặt để tránh việc ngời ta dẫn xuất tới lớp nhằm để can thiệp vào tính riêng t thành phần lớp
- Tất thành phần public lớp sở truy nhập đợc bên trong phạm vi lớp dẫn xuất Việc truy nhập đến thành phần lớp sở từ bên phạm vi lớp dẫn xuất đợc điều khiển từ khoá định quyền truy nhập đặt trớc tên lớp sở định nghĩa lớp dẫn xuất Nếu lớp dẫn xuất khai báo lớp sở public thành phần public lớp sở trỏ thành những thành phần public lớp dẫn xuất Nếu lớp dẫn xuất khai báo lớp cơ sở private, thành phần public lớp cở sở trở thành thành phần private lớp dẫn xuất Chú ý lại điều ảnh hởng đến việc truy nhập thành phần public lớp sở từ bên phạm vi lớp dẫn xuất
VÝ dô 4.2
#include <iostream.h> #include <conio.h> class Base{
private: int x; public:
void set(int i){ x=i;
}
void print(){ cout<<x<<”\n”; }
};
class Derived1:public Base{ public:
void printx(){
(45)};
class Derived2:private Base{
//Cac phan cua lop Derived2 };
void main(){
Derived1 d1; Derived2 d2;
//Hai dong thuc hien tot d1.Set(1);
d1.printx();
//Hai dong sau SAI vi ham print() va set() la ham private cua lop Derived2 d2.set(2);
d2.print(); }
Không bắt buộc phải ln có từ khố định truy xuất cho lớp sở Nếu khơng có từ khoá định, lớp sở đợc khai báo với từ khoá class đợc xem lớp sở private, lớp sở đợc khai báo với từ khoá struct đợc xem lớp sở public Từ khố xác định truy nhập có bảo vệ (protected)
Đơi cần lớp dẫn xuất để truy nhập thành phần lớp sở, nhiên lại không muốn thành phần lớp sở đợc khai báo public Khi từ khố protected đợc dùng đê xác định quyền truy nhập lớp sở Các thành phần định nghĩa phần protected lớp sở đợc xem nh public bên phạm vi lớp dẫn xuất đó, chúng đợc xem nh private lớp khác
VÝ dô 4.3
#include <iostream.h> #include <conio.h> class Base{
protected: int x; public:
void set(int i){ x=i;
}
void print(){ cout<<x<<"\n"; }
};
class Derived1:public Base{ public:
void printx(){
(46)};
void main(){ Base b;
Derived1 d1;
//Ba dong thuc hien tot d1.set(1);
d1.print(); b.set(2);
int i=b.x; //Sai vi “x” la phan protected }
Chú ý: Một thành phần protected lớp sở public đợc xem nh thành phần protected lớp dẫn xuất Một thành phần protected lớp sở private đợc xem nh thành phần private lớp dẫn xuất.
4.2.2.Định nghĩa lại hàm thành phần lớp dẫn xuÊt
- Sự định nghĩa lại hàm thành phần khác với định nghĩa chồng hàm thành phần + Hàm định nghĩa lại hàm bị định nghĩa lại giống tên, tham số trả về, khác vị trí hàm đợc đặt lớp dẫn xuất hàm đợc đặt lớp sở Ví dụ hàm void display() ví dụ 4.1
+ Hàm chồng trùng tên, nhng thờng khác dánh sách tham số tất chúng thuộc lớp
- C++ cho phép khai báo bên lớp dẫn xuất thành phần liệu tên với thành phần liệu có lớp sở Hai thành phần tên có kiểu liệu hay khác kiểu liệu Lúc bên đối tợng lớp dẫn xuất có hai thành phần trùng tên, nhng phạm vi lớp dẫn xuất tên chung định thành phần đợc khai báo lớp dẫn xuất, muốn truy nhập thành phần tên lớp sở sở, phải sử dụng tên lớp sở toán tử phạm vi “::” đặt trớc thành phần
VÝ dơ 4.4
#include <iostream.h> #include <conio.h> class Base{
protected: int x; public:
Base(int i){ x = i;
} };
class Derived:public Base{ private:
int x; public:
Derived(int i){
(47)}
void sum(){
int s=x+Base::x; cout<<"x="<<x<<"\n"; cout<<"Base::x="<<x<<"\n";
cout<<"sum ="<<s<<"\n"; }
};
void main(){ Base b(1); Derived d(2); d.sum();
getch(); }
4.2.3.TÝnh kÕ thõa líp dÉn xuÊt
- Một đối tợng lớp dẫn xuất “thay thế” đối tợng lớp sở Nghĩa tất thành phần liệu có lớp sở tìm thấy lớp dẫn xuất, tất hàm thực lớp cở sở ln thực đợc lớp dẫn xuất
- Ví dụ: Một đối tợng m lớp coloredpoint đồng thời có hai thành phần toạ độ x,y thêm thành phần liệu bổ sung color, gọi hàm thành phần point::display() point::move() thông qua đối tợng m Tức là:
m.move(4,5);
m.display(); // (x,y,mau)=(5,7,3); m.point::move(6,7);
m.display();
- Ngợc lại, đối tợng lớp sở thay lớp dẫn xuất Ví dụ: point p;
p.display();// Goi ham point::display() coloredpoint n(2,3,5);
n=p;// Sai
- Tính tơng thích trỏ lớp dẫn xuất trỏ lớp sở Một trỏ đối tợng lớp sở đến đối tợng lớp dẫn xuất, ngợc lại trỏ lớp dẫn xuất nhận địa đối tợng lớp sở, trừ trờng hợp ép kiểu
VÝ dô:
point *p;
coloredpoint m(1,2,3);
p=&m;//p chua dia chi cua m p->move(4,5);
p->display();//Goi point::display() m.display();
(48)VÝ dô:
coloredpoint m(1,2,3); point p=&m;
p.move(4,5); //point::move() p.display(); //point::display()
m.display(); //coloredpoint::display();
4.2.4.Hµm thiÕt lËp líp dÉn xuÊt
- Một đối tợng lớp dẫn xuất thực chất coi đối tợng lớp sở, thêm thành phần lớp dẫn xuất việc gọi hàm thiết lập lớp dẫn xuất để tạo đối tợng lớp dẫn xuất kéo theo việc gọi đến hàm thiết lập lớp sở
- Về nguyên tắc, phần đối tợng lớp dẫn xuất thuộc lớp sở đợc tạo tr-ớc thông tin đợc xác lập Nh hàm thiết lập cho lớp sở đợc tạo trớc hàm thiết lập cho lớp dẫn xuất
- Các lớp dẫn xuất kế thừa hàm thiết lập lớp sở Các hàm thiết lập lớp dẫn xuất phải chứa thông tin đối số cho hàm thiết lập lớp sở Tức định nghĩa hàm thiết lập lớp dẫn xuất phải định nghĩa lời gọi tới hàm thiết lập lớp sở
VÝ dô:
coloredpoint():point(){ color=0;
}
coloredpoint(float ox, float oy, unsigned int c):point(ox,oy){
color=c; }
coloredpoint (coloredpoint &b):point((point &)b){ color=b.color;
}
4.2.5.Sù kÕ thõa nhiÒu líp
Một lớp có nhiều lớp sở Điều đợc gọi kế thừa nhiều lớp Ví dụ:
class Base1{ protected:
int b1; public:
void Set(int i){b1=i;} };
(49)int b2; public:
void Set(int i){b2=i;} int Get(){return b2;} };
class Derived:public Base1, public Base2{ public:
void Print(){
cout<<”b1=”<<b1<<”b2=”<<Get()<<"\n"; }
};
Lớp Derived kế thừa từ hai lớp Base1 Base2 Lớp Base1 Base đợc khai báo lớp sở public Do lớp Derived truy nhập trực tiếp thành phần liệu public protected Base1, nhng truy nhập thành phần public lớp Base2
Việc sử dụng nhiều lớp sở tạo điểm mơ hồ khác chơng trình C++ Ví dụ: Với khai báo sau:
Derived d; d.Set(10);
Thì chơng trình dịch cảnh báo việc truy nhập đến hàm Set(), chơng trình khơng thể xác định kiểu truy nhập để áp dụng cho hàm Do lệnh d.Set(10) sai
Để định hàm Set() đợc gọi, lệnh gọi phải nh sau: d.Base1::Set(10);
d.Base2::Set(10);
- Nếu lớp có nhiều lớp sở, tham số thiết lập cho tất lớp sở đợc nêu hàm thiết lập lớp dẫn xuất
VÝ dô:
class Base1{ private: int x; public:
Base1(int i){x=i;} };
class Base2{ private:
int y; public:
Base1(int i){y=i;} };
(50)public:
Derived(int i):Base1(i), Base2(0){ //Rong
} };
- Nếu có lớp sở không định nghĩa hàm thiết lập khơng tham số, lớp dẫn xuất từ phải định nghĩa hàm thiết lập gọi đến hàm thiết lập lớp sở với tham số yêu cầu
VÝ dô:
class Base1{ private:
int x; public:
Base1(int i){x=i;} };
class Base2{ private:
int y; public:
Base2(){y=0;}
Base2(int i){y=i;} };
class Derived:public Base1, private Base2{ public:
Derived(int x):Base1(x){ // Rong
}; };
Mặc dù Base2 có định nghĩa cặp hàm thiết lập, nhng có hàm thiết lập khơng có tham số (ngầm định) Điều có nghĩa hàm thiết lập cho lớp dẫn xuất từ Base2 không thiết phải gọi hàm thiết lập cho lớp Base2 Ngợc lại, Base1 định nghĩa hàm thiết lập mà phải có tham số Do hàm thiết lập lớp dẫn xuất Derived bắt buộc phải gọi hàm thiết lập Base1
4.3 Lớp sở ảo
(51)lóp dẫn xuất Tuy nhiên có trờng hợp lớp sở đợc sử dụng nhiều hơn lần lớp sở tổ tiên của một lớp dẫn xuất Điều phát sinh ra lỗi, khơng có cách để phân biệt hai lớp sở gốc.
XÐt vÝ dô minh ho¹ sau:
#include<iostream.h> #include<conio.h>
class A{ public:
float v1; };
class B:public A{ public:
float v2; };
class C:public A{ public:
float v3; };
class D:public B, public C{ public:
float v4; };
void main(){
(52)obj.v4=1; obj.v3=2; obj.v2=3;
obj.v1=4; //Mơ hồ }
Mô h×nh kÕ thõa nh sau:
Thành phần v1 obj hàm main::v1 là thành phần A mà A lớp sở public cho hai lớp sở D (là lớp B và lớp C) Nói cách khác, có hai lớp sở A cho lớp D chơng trình dịch khơng thể nào nhận biết đợc phép gán cho v1 đợc kế thừa thông qua B hay v1 kế thừa thông qua C.
Giải pháp cho vấn đề khai báo A là một lớp sở kiểu virtual (lớp sở ảo) cho B C Định nghĩa lớp B và C nh sau:
KÕ thõa KÕ thõa KÕ thõa KÕ thõa
class A - v1
class B - v2
class C - v3
(53)class B: virtual public A{ public:
double v2; };
class C: virtual public A{
public:
float v3; };
Chú ý: Khái niệm lớp sở kiểu virtual tơng đối khó sử dụng, thiết kế chơng trình cần phải có kế hoạch suy tính để nhiều lớp đợc kết họp lại, sau cân nhắc xem lớp cần phải tạo theo virtual
Ngay với lớp sở kiểu virtual, có lớp với nhiều lớp sở mà l¹i thõa hëng nhiỊu gèc cđa cïng mét líp
VÝ dô:
class A{ public:
int v1; }; //Líp gèc
class B:virtual public A{ public:
double v2; }; //Líp gèc
class C:virtual public A{ public:
float v3; }; //Líp gèc
class X: public A{ public:
double v5; }; //Líp gèc
class D: public B, public C, public X{ public:
char v4; };
(54)4.4.TÝnh tơng ứng bội (polymorphism) 4.4.1 Khái niệm tính tơng øng béi
Khái niệm tơng ứng bội nh khả xử lý lớp liên hệ với đối tợng theo cách tổng quát
Chóng ta xÐt vÝ dơ sau: VÝ dơ 1:
#include<iostream.h> #include<conio.h> class point{
private: float x,y; public:
point(){ x=0;y=0; }
point(float ox, float oy){ x=ox;y=oy;
}
point(point &p){ x=p.x;y=p.y; }
//Dinh nghia ham ao virtual void display(){
cout<<"\n Toa x="<<x<<" y ="<<y; }
void move(float dx,float dy){ x+=dx;y+=dy;
} };
//Ke thua tu lop point
class coloredpoint:public point{ private:
unsigned int color; public:
coloredpoint():point(){ color=0;
}
coloredpoint(float ox, float oy,unsigned int c):point(ox,oy){ color=c;
}
coloredpoint(coloredpoint &b):point((point &)b){ color=b.color;
(55)virtual void display(){ point::display();
cout<<"\n Color ="<<color; }
};
void main(){ clrscr();
coloredpoint pc(2,3,4);
pc.display(); //Goi ham display cua lop coloredpoint point p(2,3);
p.display(); //Goi ham display cua lop point point *ptr;
ptr=&p;
ptr->display(); //Goi ham display cua lop point ptr=&pc;
ptr->display(); //Goi ham display cua lop coloredpoint getch();
}
NhËn xÐt:
- Trong định nghĩa lớp point, dòng tiêu đề khai báo hàm thành phần display() có từ khoá virtual để hàm display() hàm ảo Từ khố virtual đặt trớc sau tên kiểu liệu nhng phải đặt trớc tên hàm Hàm display() lớp point đợc định nghĩa lại lớp dẫn xuất Khi tuỳ thuộc vào kiểu đối tợng có địa chứa trỏ ptr mà lời gọi hàm ptr->display() gọi đến hàm display() lớp point hay lớp coloredpoint, tính chất đợc hiểu nh tính tơng ứng bội
- Tính tơng ứng bội thể hàm thành phần lớp sở đợc gọi từ đối tợng lớp dẫn xuất, cịn thân hàm gọi tới hàm thành phần đ ợc định nghĩa đồng thời lớp sở (có khai báo virtual) lớp dẫn xuất Xét ví dụ sau:
#include<iostream.h> #include<conio.h> class point{
private: float x,y; public:
point(){
x=0;y=0; }
point(float ox, float oy){ x=ox;y=oy;
}
point(point &p){
(56)}
void display(){
cout<<"\n Toa x="<<x<<" y ="<<y; identifier();
}
//Dinh nghia ham ao
virtual void identifier(){ cout<<"\n Diem khong mau"; }
void move(float dx,float dy){ x+=dx;y+=dy;
} };
//Ke thua tu lop point
class coloredpoint:public point{ private:
unsigned int color; public:
coloredpoint():point(){ color=0;
}
coloredpoint(float ox, float oy,unsigned int c):point(ox,oy){ color=c;
}
coloredpoint(coloredpoint &b):point((point &)b){ color=b.color;
}
virtual void identifier(){ cout<<"\n Color="<<color; }
};
void main(){ clrscr();
coloredpoint pc(2,3,4);
pc.display(); //Ham display() goi ham identifier() cua lop coloredpoint point p(2,3);
p.display(); //Ham display() goi ham identifier() cua lop point point *ptr;
ptr=&p;
ptr->display();//Ham display() goi ham identifier() cua lop point
(57)ptr->display();//Ham display() goi ham identifier() cua lop coloredpoint getch();
}
Trong ví dụ này, tuỳ thuộc vào đối tợng mà hàm display() lớp point gọi đến hàm identifier() lớp point hay hàm identifier() lớp coloredpoint
4.4.2.Những đặc trng hàm virtual
- Việc định nghĩa hàm ảo lớp sở lớp dẫn xuất cần phải thống Điều có nghĩa tất hàm virtual phải đợc định nghĩa có cùng tên, danh sách danh sách đối số kiểu trả Nếu kiểu hàm khác nhau, từ khố virtual bị bỏ qua chơng trình biên dịch hiểu lớp dẫn xuất đã gạt hàm này
- Vì hàm virtual dựa lớp nguyên thuỷ đối tợng mà qua chúng đợc gọi, nên chúng phải có đối tợng ẩn chúng phải thành phần thật lớp Điều nghĩa hàm friend virtual đợc Tuy nhiên hàm virtual lớp đợc khai báo friend lớp khác
- Không bắt buộc phải ghi rõ từ khoá virtual định nghĩa hàm virtual lớp dẫn xuất, nhiên nên ghi từ khoá vào hàm lớp dẫn xuất làm nh cho ta nhìn rõ ý đồ
- Nếu lớp dẫn xuất không định nghĩa phơng thức tơng ứng bội riêng C++ sử dụng hàm định nghĩa cho lớp c s
4.4.3 Ví dụ thêm tính tơng ứng bội
Để hiểu rõ tính tơng øng béi, ta xÐt thªm vÝ dơ sau:
Cơ X có chuồng ni thú Chiếc chuồng gồm 20 ngăn, cô thờng để mèo số ngăn chó số ngăn lại Hãy xây dựng chơng trình hớng đối tợng đơn giản để quản lý ngăn chuồng Có bốn lớp đợc định nghĩa cho bi toỏn nh sau:
- Định nghĩa lớp c¸c vËt:
class Animal{ protected:
char *Name; public:
Animal(){Name=NULL;}
Animal(char *n){Name=strdup(n);} ~Animal(){delete Name;}
void WhoAmI(){cout<<”Con vat chung ”<<"\n";} };
Lớp Animal (con vật) lớp sở mà từ lớp Dog (chó) Cat (mèo) đợc dẫn xuất Khi Animal đợc xây dựng, đợc đặt tên để lu trữ với đối tợng Lớp Animal định nghĩa phần tử liệu chung (một trỏ đến chuổi tên) hàm thiết lập hàm huỷ bỏ cho hai lớp đợc dẫn xuất từ (Cat Dog) Thành phần liệu Name đợc khai báo protected, nh đợc truy nhập dẫn xuất mà không cn khai bỏo nú l public
- Định nghĩa lớp mèo:
(58)Cat():Animal(){//rỗng}
Cat(char *n):Animal(n){//rỗng}
void WhoAmI(){cout<< Toi la chu meo <<Name<<"\n";} };
- Định nghĩa lớp chó:
class Dog:public Animal{ public:
Dog():Animal(){//rỗng}
Dog(char *n):Animal(n){//rỗng}
void WhoAmI(){cout<< Toi la chu cho ”<<Name<<"\n";} };
Các lớp Cat Dog giống Mỗi lớp định nghĩa hàm thiết lập tuý gửi tham số cho hàm thiết lập lớp sở (Animal) Hơn nữa, hai lớp có phơng thức gọi WhoAmI() (tôi ai) để hiển thị thông báo loi v tờn i t-ng
- Định nghĩa lớp chuång:
class Kennel{ private:
unsigned int MaxCats; unsigned int NumCats; Cat **Kitties; //Nh÷ng mÌo
unsigned int MaxDogs; unsigned int NumDogs;
Dog **Doggies; //Nh÷ng chã public:
Kennel(unsigned int maxc, unsigned int maxd); ~Kennel();
//Phơng thức đa chó vào chuồng unsigned int Accept(Dog *d);
unsigned int Accept(Cat *c); // Định nghĩa chồng hàm
//Phơng thức lấy chó khái chuång
Dog *ReleaseDog(unsigned int pen); //pen – Sè chuång
Cat *ReleaseCat(unsigned int pen); //pen – Sè chuång
void ListAnimals(); };
Các phơng thức cho Kennel phức tạp, không nên dùng dạng inline, định nghĩa phơng thức bên ngồi lớp Về lớp Kennel có chứa trỏ đến hai mảng, trỏ đầu đến nhứng đối tợng Dog, trỏ thứ hai đến đối tợng Cat Các thành phần liệu khác lu trữ kích thớc mảng, số vị trí mảng thật chứa vật
Tiếp theo, cần định nghĩa phơng thức cho lớp Kennel
(59)MaxDogs=maxd; NumCats=0; NumDogs=0;
Kitties=new Cat *[MaxCats]; Doggies=new Dog *[MaxDogs];
for (int i=0;i<MaxCats;i++) Kitties[i]=NULL; for (int j=0;j<MaxDogs;j++) Doggies[j]=NULL; }
Hàm thiết lập cho lớp Kennel nhận hai tham số định nghĩa số lợng lớn chó mèo mà chuồng chứa
Kennel::~Kennel(){ delete Kitties; delete Doggies; }
Có hai phơng thức có tên Accept, phơng thức nhận tham số trỏ đến Dog, phơng thức nhận tham số trỏ đến Cat Đây ví dụ cho việc định nghĩa chồng hàm
unsigned int Kennel::Accept(Dog *d){ if (NumDogs==MaxDogs) return 0; ++NumDogs;
int i=0;
while (Doggies[i]!=NULL) ++i; Doggies[i]=d;
return i+1; }
unsigned int Kennel::Accept(Cat *c){ if (NumCats==MaxCats) return 0; ++NumCats;
int i=0;
while (Kittiess[i]!=NULL) ++i; Kitties[i]=c;
return i+1; }
Phơng thức Accept lu trữ trỏ nhận đối số vào mảng cho loại thú tơngứng, cịn trống trả số chuồng (pen) mà vật đợc nhốt Trong trờng hợp ngợc lại trả
Dog *Kennel::ReleaseDog(unsigned int pen){ if (pen>MaxDogs) return NULL;
pen;
if (Doggies[pen]!=NULL){ Dog *temp=Doggies[pen]; Doggies[pen]=NULL;
NumDogs; return temp;
}
(60)Cat *Kennel::ReleaseCat(unsigned int pen){ if (pen>MaxCats) return NULL;
pen;
if (Kitties[pen]!=NULL){ Cat *temp=Kitties[pen]; Kitties[pen]=NULL;
NumCats; return temp;
}
else return NULL; }
Các phơng thức ReleaseDog() ReleaseCat() lấy vật khỏi chuồng nó, tức nhận tham số cho biết chuồng cần phải làm trống Nếu chuồng trống, phơng thức trả trỏ NULL, ngợc lại chúng “làm trống” chuồng việc gán cho trỏ NULL trả trỏ đến vật mà cất vào trớc Phơng thức ReleaseDog() trả trỏ đến đối tợng Dog, phơng thức ReleaseCat() trả trỏ đến đối tợng Cat Các phơng thức khác kiểu trả chúng chúng phải có tên khác khơng thể định nghĩa chồng đợc
Cuối phơng thức ListAnimals() dùng để hiển thị danh sách vật nhốt chuồng Điều đợc thực cách gọi phơng thức WhoAmI() cho trỏ khác NULL mảng Doggies Kitties
void Kennel::ListAnimals(){ if (NumDogs>0)
for (int i=0;i<MaxDogs;i++) if (Doggies[i]!=NULL){
cout<<”Con cho o "<<i<<” noi ” Doggies[i]->WhoAmI();
} if (NumCats>0)
for (int j=0;j<MaxCats;j++) if (Kitties[j]!=NULL){
cout<<”Con meo o "<<j<<” noi ” Kitties[j]->WhoAmI();
} }
Cuối hàm main() dùng để kiểm tra modul
void main(){
Kennel K(10,10); // Toi da co 10 cho va 10 meo Dog d1(“Rover”);
Dog d2(“Spot”); Dog d3(“Chip”); Dog d4(“Buddyr”); Dog d5(“Butch”);
Cat c1(“Tinkerbell”); Cat c2(“Inky”);
(61)Cat c5(“Sylvester”);
//Cac thu duoc dua vao va lay K.Accept(&d1);
unsigned int c2pen=K.Accept(&c2); K.Accept(&d3);
K.Accept(&c1);
unsigned int d4pen=K.Accept(&d4); K.Accept(&d5);
K.Accept(&c5);
K.ReleaseCat(c2pen); K.Accept(&c4);
K.Accept(&c3);
K.ReleaseDog(&d4pen); K.Accept(&d2);
K.ListAnimals(); getch();
}
Phân tích chơng trình viết:
- Chơng trình chạy đợc nhiên số hạn chế:
+ Điều xẩy X có 15 chó mèo ? Cơ phải thay đổi chơng trình để định nghĩa ngăn cho mèo 15 ngăn cho chó Mỗi lần thay đổi pha trộn chó mèo, cô X phải thay đổi định nghĩa đối tợng Kennel K Rõ ràng điều không hợp lý
+ Cô X cần thêm lợn vào chuồng, điều có nghĩa cần phải thay đổi lớp Kennel để đa vào lớp này, tức phải thêm thành phần liệu mới, thay đổi hàm thiết lập cần thêm vào phơng thức Rõ ràng cần phải làm lại toàn q trình có thêm lồi thú mi xut hin
Ví dụ: Xây dựng lại toán dạng tổng quát, sử dụng tính tơng ứng béi #include <string.h>
#include <iostream.h> #include <conio.h> class Animal{ protected: char *Name; public:
Animal(){Name=NULL;}
Animal(char *n){Name=strdup(n);} ~Animal(){delete Name;}
virtual void WhoAmI(){ cout<<"Con vat chung \n";
}
};
(62)public:
Cat():Animal(){/*rong*/}
Cat(char *n):Animal(n){/*rong*/} virtual void WhoAmI(){
cout<<"Toi la meo ten la "<<Name<<"\n"; }
};
/* -*/ class Dog:public Animal{
public:
Dog():Animal(){/*rong*/}
Dog(char *n):Animal(n){/*rong*/} virtual void WhoAmI(){
cout<<"Toi la cho ten la "<<Name<<"\n"; }
};
/* -*/ class Kennel{
private:
unsigned int MaxAnimals; unsigned int NumAnimals; Animal **Resident;
public:
Kennel(unsigned int max); ~Kennel();
unsigned int Accept(Animal *d); Animal *Release(unsigned int pen); void ListAnimals();
};
/* -*/ Kennel::Kennel(unsigned int max){
MaxAnimals=max; NumAnimals=0;
Resident= new Animal *[MaxAnimals]; for (int i=0; i<MaxAnimals;i++) Resident[i]=NULL;
}
/* -*/ Kennel::~Kennel(){delete Resident;}
(63)unsigned int Kennel::Accept(Animal *d){ if (NumAnimals==MaxAnimals) return 0; ++NumAnimals;
int i=0;
while (Resident[i]!=NULL) ++i; Resident[i]=d;
return i+1; }
Animal *Kennel::Release(unsigned int pen){ if (pen>MaxAnimals) return NULL;
pen;
if (Resident[pen]!=NULL){
Animal *temp=Resident[pen]; Resident[pen]=NULL;
NumAnimals; return temp; }
else return NULL; }
void Kennel::ListAnimals(){ if (NumAnimals>0)
for (int i=0;i<MaxAnimals;i++) if (Resident[i]!=NULL){
cout <<"Con vat o "<<i<<" noi "; Resident[i]->WhoAmI();
} }
(64)Kennel K(20);
//Cac thu duoc dua vao va lay K.Accept(&d1);
unsigned int c2pen=K.Accept(&c2); K.Accept(&d3);
K.Accept(&c1);
unsigned int d4pen=K.Accept(&d4); K.Accept(&d5);
K.Accept(&c5); K.Release(c2pen); K.Accept(&c4); K.Accept(&c3); K.Release(d4pen); K.Accept(&d2); K.ListAnimals(); getch();
}
- Có hai bổ sung cần ý định nghĩa hàm đợc thay đổi chơng trình ngắn đáng kể
- Hầu hết vấn đề phiên trớc nảy sinh từ việc xử lý riêng lẽ đối tợng Cat Dog Phiên định nghĩa lại lớp Cat Dog để chúng đợc xử lý giống nh chúng có liên quan với Suy cho chúng có liên hệ với chúng chia lớp sở, lớp Animal
- Trong ví dụ này, phơng thức WhoAmI() đợc định nghĩa cho lớp Animal với từ khoá virtual Từ khoá virtual đợc bổ sung vào định nghĩa WhoAmI() trong lớp Dog Cat (tuy nhiên điều nàylà không cần thiết) Bây giờ, trỏ tới đối tợng Dog đợc gán cho trỏ tới đối tợng Animal, lúc phơng thức WhoAmI() đợc gọi qua trỏ đến Animal, phơng thức WhoAmI() tơng ứng với lớp Dog đợc gọi Tơng tự, phơng thức WhoAmI() tơng ứng với lớp Cat đợc gọi trỏ đến đối tợng Cat đợc gán cho trỏ Animal, mà qua WhoAmI() đợc gọi
- Vấn đề làm để thêm vào lợn Tính tơng ứng bội cũng giải tốn X, việc thêm vào lợn đơn giản thêm định nghĩa lớp vào chơng trình:
class Pig:public Animal{ public:
Pig():Animal(){/*rong*/}
Pig(char *n):Animal(n){/*rong*/}
(65)Trong thực tế, X dẫn xuất lớp từ lớp Animal Chẳng hạn, cô ta muốn tách riêng giống mèo thành giống mèo đực mèo Cô ta cần thực nh sau:
class FemaleCat:public Cat{ public:
FemaleCat():Animal(){/*rong*/}
FemaleCat(char *n):Animal(n){/*rong*/}
virtual void WhoAmI(){cout<<"Toi la meo cai ten la "<<Name<<"\n";} };
class MaleCat:public Cat{ public:
MaleCat():Animal(){/*rong*/}
MaleCat(char *n):Animal(n){/*rong*/}
virtual void WhoAmI(){cout<<"Toi la meo duc ten la "<<Name<<"\n";} };
Khi ta dùng đối tợng Malecat, FemaleCat giống nh đối tợng Cat, Dog, Pig
Thế mạnh tính ứng bội có hai cấp Thứ nhất, cho phép ta xử lý khái niệm có liên hệ với theo cách giống nhau, làm cho chơng trình tổng quát dễ hiểu Thứ hai, tính tơng ứng bội dùng để viết chơng trình mở rộng nhiều Khi loại đợc thêm vào có liên hệ với kiểu có chất tơng ứng bội làm cho loại thích hợp vào hệ thống mà khơng địi hỏi phải thay đổi phần cịn lại chng trỡnh
4.4.4 Các lớp sở trừu tợng (Abstract Base Classes)
Một lớp sở trìu tợng lớp đợc dùng làm sở cho lớp khác Khơng có đối tợng lớp trừu tợng đợc tạo cả, đợc dùng để định nghĩa số khái niệm tổng quát chung cho lớp khác Một ví dụ lớp trừu tợng lớp Animal ví dụ
Trong C++, thuật ngữ "lớp trừu tợng" đặc biệt áp dụng cho lớp có chứa các phơng thức virtual tuý Một phơng thức virtual tuý phơng thức virtual mà định nghĩa lớp đợc định nghĩa "Khơng có gì " Ví dụ sau lớp sở trừu tợng
class Abstract{ public:
void print()=0; void process()=0; int status(); };
Phơng thức print() process() đợc khai báo phơng thức tuý cách gán thay cho việc cài đặt hàm Phuơng thức status hàm thành phần bình th-ờng phải có định nghĩa
(66)nào dẫn xuất từ lớp sở trừu tợng phải khai báo lại tất phơng thức virtual tuý mà thừa hởng Một lớp dẫn xuất phải định nghĩa lại tất phơng thức virtual tuý mà thừa hởng, phơng thức virtual, định nghĩa hàm thực
VÝ dô:
class Derived: public Abstract{ public:
void print()=0; void process(){
// Dinh nghia cua lop Derived cho ham
} };
(67)Chơng 5.Mô hình
5.1 Mô hình hàm
Trong lập trình nhiều gặp loạt hàm giống giải thuật, khác kiểu liệu Để tránh việc viết lặp lại giải thuật, C++ cho phép xây dựng mô hình hàm chung cho kiểu liƯu
Xét ví dụ hàm tìm max cho kiểu liệu khác cách định nghĩa chồng hàm
int max(int a, int b){return (a>b)? a:b;}
double max(double a, double b){return (a>b)? a:b;}
Các hàm khác điểm kiểu liệu Còn nhiều kiểu liệu mà ta cha định nghĩa nh char, long, float, tiếp tục định nghĩa chồng hàm nh thời gian Trong C++ cho phép viết mơ hình giải thuật chung cho hàm max thay kiểu liệu cụ thể int, double kiểu tên lớp trung gian Tên lớp trung gian đợc thay kiểu liệu cụ thể nh int, double phụ thuộc vào kiểu liệu truyn vo cho hm max
5.1.1 Định nghĩa sư dơng
Để định nghĩa mơ hình hàm ta dùng từ khoá template nh sau:
template <class T>
T max(T a, T b) {return (a>b) ? a:b;}
Khai báo template <class T> có nghĩa T tên lớp mơ hình T đợc thay kiểu liệu cụ thể nh int, double, sử dụng mơ hình Sử dụng mơ hình hàm giống nh gọi hàm bình thờng Khi có lời gọi hàm max với tham số truyền vào, chơng trình dịch nhận biết kiểu liệu truyền vào tự động sinh hàm max (hàm thể hiện) với kiểu liệu T đợc thay th bng kiu d liu truyn vo
Hàm tìm max cã thĨ viÕt l¹i nh sau: #include <iostream.h> #include <conio.h> template <class T>
T max(T x, T y){return (x > y) ? x : y;} void main(){
int a=5,b=6;
cout<<"Max cua a,b "<<max(a,b); //T duoc thay bang int double x=5.5,y=6.5;
cout<<"Max cua x,y "<<max(x,y); //T duoc thay bang double getch();
}
(68)Trong mô hình hàm hoàn toàn nhiều lớp làm lớp mô hình Ví dụ ta khai báo lớp có hai lớp mô hình T U nh sau:
template <class T, class U> void fct(T a, U b){
//Néi dung hàm }
5.1.2.Giới hạn mô hình hàm
- Các tham số truyền vào cho mơ hình hàm phải đảm bảo cho trình biên dịch ánh xạ 1-1 việc thay lớp mơ hình kiêu liệu thực Ví dụ lời gọi hàm max(a,b) với a int b double gây lỗi Vì theo mơ hình hàm a b phải tham số có kiểu T Nh lúc chơng trình dịch khơng thể biết thay T int hay double
- Mơ hình hàm ứng dụng đợc cho lớp liệu mà có hàm, tốn tử, hàm thiết lập đợc sử dụng mơ hình Ví dụ nh lớp phân số khơng có tốn tử > ta khơng thể gọi mơ hình max với lớp phân số mơ hình sử dụng tốn t >
5.1.3.Cụ thể hoá mô hình hàm
- Xét việc dùng mô hình max với kiểu liƯu x©u nh sau:
char *s1=”SPTIN”; char *s2=”CNTIN”;
Theo định nghĩa mơ hình việc so sánh xâu dựa toán tử so sánh > Nh việc so sánh lúc so sánh địa xâu việc truyền liệu vào trỏ trỏ đến xâu Mà công việc cần thiết phải so sánh nội dung hai xâu đ a vào địa chúng Để làm điều phải dùng hàm so sánh xâu khơng phải tốn tử > Nh kiểu liệu xâu (char *) hàm max khơng theo mơ hình chung nh kiểu liệu int, float, double Trong trờng hợp C++ cho phép cụ thể hoá hàm max cho kiểu liệu xâu Từ hàm max mà sử dụng kiểu liệu xâu theo hàm đợc cụ thể mà khơng theo mơ hình chung
Chơng trình đợc viết lại nh sau: #include <iostream.h> #include <conio.h> #include <string.h> template <class T> T max(T x, T y){
return (x > y) ? x : y; }
char *max(char *s1, char *s2){
return (strcmp(s1,s2)>0) ? s1 : s2; }
void main(){ int a=5,b=6;
(69)cout<<"Max cua x,y "<<max(x,y); //T duoc thay bang double char *s1=”SPTIN”;
char *s2=”CNTIN”;
cout<<"Max cua s1,s2 "<<max(s1,s2); // goi ham max cu the getch();
}
Nh chất việc cụ thể hoá mơ hình định nghĩa hàm trùng tên cho kiểu dữ liệu đặc biệt mà thuật tốn cho khụng tuõn theo mụ hỡnh chung.
5.2 Mô hình líp
- Cũng giống nh mơ hình hàm, C++ cho phép viết mơ hình lớp chung cho kiểu liệu, sau áp dụng cho kiểu liệu khác để đợc lớp thể cụ thể
- Gi¶ sư ta cã lớp điểm mặt phẳng, phụ thuộc vào mặt phẳng chúng rời rạc hay liên tục mà ta có liệu thành phần int hay double Lớp điểm có dạng nh sau:
- Lớp điểm mặt phẳng rời rạc:
class point{
private:
int x,y; public:
point(int ox=0, int oy=0){ x=ox;y=oy;
}
void move(int dx, int dy){ x+=dx;y+=dy;
}
void display(){
cout<<"\n x="<<x<<" y ="<<y; }
};
- Lớp điểm mặt phẳng liên tục:
class point{
private:
float x,y; public:
point(float ox=0,float oy=0){ x=ox;y=oy;
}
void move(float dx,float dy){ x+=dx;y+=dy;
}
void display(){
cout<<"\n x="<<x<<" y ="<<y; }
(70)Nhìn vào hai lớp dẽ thấy chúng khác điểm kiểu liệu thành phần int float Nh ta hoàn toàn viết mô hình lớp chung với lớp mô hình thay cho liệu cụ thể
5.2.1 Định nghĩa sử dụng
định nghĩa mơ hình lớp, ta sử dụng từ khố template giống nh mơ hình hàm Tên trung gian lớp mơ hình ngời sử dụng đặt
Ví dụ: Định nghĩa mô hình lớp point template <class T>
class point{ private:
T x,y; public:
point(T ox=0,T oy=0){ x=ox;y=oy;
}
void move(T dx,T dy); void display(){
cout<<"\n x="<<x<<" y ="<<y; }
};
Định nghĩa hàm thành phần cho lớp mô h×nh
template <class T>
void point<T>::move( T dx, T dy){ x+=dx;y+=dy;
}
Để định nghĩa hàm thành phần mơ hình ta phải nhắc lại khai báo mơ hình template nh định nghĩa với hàm move() Sau có mơ hình lớp ta sử dụng chúng với kiểu liệu khác nhau, chí lớp ngời sử dụng Với kiểu liệu, chơng trình dịch tạo lớp thể tơng ứng
VÝ dô:
- Khai báo đối tợng với lớp thể kiểu int
point<int> pi(5,6);
- Khai báo đối tợng với lớp thể kiểu double
point<double> pd(5.5,6.5);
- Cã thĨ sư dơng nhiỊu h¬n mét líp mô hình mô hình lớp giống nh mô hình hàm Ví dụ mô hình sử dụng hai lớp:
template <class T, class U> class Example{
(71)5.2.2.Giới hạn mô hình lớp
Cng giống nh mơ hình hàm, mơ hình lớp áp dụng cho lớp liệu mà có thành phần, toán tử, hàm thiết lập mà đợc sử dụng mơ hình lớp Ví dụ mơ hình lớp point có sử dụng đến tốn tử += hàm thành phần move() toán tử (<<) hàm thành phần display() Do mơ hình lớp point ứng dụng với lớp mà có tốn tử sử dụng mơ hình
5.2.3.Cơ thể hoá mô hình lớp
Ging nh mụ hỡnh hàm ngời ta sử dụng cụ thể hố mơ hình cho kiểu liệu đặc biệt Tuy nhiên mơ hình lớp cụ thể hố hàm thành phần lớp - Cụ thể hố hàm thành phần
Trở lại với mơ hình lớp point cho thể liệu kiểu char Khi gọi tới hàm thành phần display(), x y kiểu liệu char nên theo định nghĩa hàm mơ hình đa hình ký tự tơng ứng mà khơng phải số Nh để tránh điều C++ cho phép định nghĩa lại thành phần liệu kiểu char (gọi cụ thể hoá thành phần) Sau cụ thể hoá hàm thành phần này, chơng trình dịch sử dụng thay cho hàm thành phần đợc định nghĩa mơ hình
//Cơ thể hoá cho lớp liệu kiểu char
void point<char>::display(){
cout<<”(“<<(int)x<<”,”<<(int)y<<”)”; }
- Cơ thĨ ho¸ líp
Khi có kiểu liệu mà định nghĩa lớp khơng tn theo mơ hình thid cụ thể hố lớp cho kiểu liệu Ví dụ cụ thể hố lớp kiểu char cho mơ hình lớp point
class point<char>{
(72)bài tập Chơng Lớp đối tợng
Bài 3.1 a Xây dựng lớp Circle mô tả đối tợng đờng trịn Lớp gồm có thành phần sau:
- Thuộc tính r số thực mơ tả bán kính đờng trịn - Hàm thiết lập khơng tham số đặt bán kính
- Hàm thiết lập tham số đặt bán kính d - Hàm thiết lập chép
- Hµm tÝnh diƯn tÝch - Hµm tÝnh chu vi - Hµm in diƯn tÝch - Hµm in chu vi
b Viết chơng trình tạo đờng trịn có bán kính k với k nhập vào từ bàn phím In hình diện tích chu vi đờng tròn
Bài 3.2 a Xây dựng lớp Rectangle mơ tả đối tợng hình chữ nhật Lớp gồm có thành phần sau:
- Các thuộc tính mơ tả chiều dài chiều rộng hình chữ nhật - Hàm thiết lập tham số với giá trị ngầm định
- Hµm thiÕt lËp chÐp - Hµm tÝnh chu vi
- Hµm tÝnh diƯn tÝch - Hµm in chu vi - Hàm in diện tích
- Hàm báo lỗi thiết lập hình chữ nhật có cạnh <0
b.Viết chơng trình nhập vào số thực a,b Tạo hình chữ nhật với chiều dài a chiều rộng b In hình diện tích chu vi hình chữ nhật
Bi 3.3: a Xây dựng lớp Circle mô tả đối tuợng đờng trịn, lớp gồm có thành
phÇn sau:
- Thuộc tính r mơ tả bán kính đờng tròn số thực - Hàm thiết lập khơng tham số đặt bán kính
- Hàm thiết lập tham số đặt bán kính d - Hàm thiết lập chép
- Hµm tÝnh diƯn tÝch
- Hµm in mµn hình diện tích hình tròn
- Khai bỏo toỏn tử + hàm bạn lớp đờng tròn b Viết tốn tử + để tính tổng diện tích hai đờng trịn
c Viết chơng trình tạo hai hình trịn có bán kính r1, r2 với r1, r2 nhập vào từ bàn phím In hình tổng diện tích hai hình trịn đờng trịn
Bài 3.4: a Xây dựng lớp Rectangle mô tả đối tợng hình chữ nhật, lớp gồm có
thành phần sau:
- Cỏc thuc tớnh mụ tả chiều dài chiều rộng số thực - Hàm thiết lập không tham số đặt cạnh
(73)- Hµm tÝnh diƯn tÝch
- Hàm in hình diện tích hình chữ nhật - Khai báo tốn tử + hàm bạn lớp Rectangle b Viết toán tử + để tính tổng diện tích hai hình chữ nhật
c Viết chơng trình tạo hình chữ nhật H1 víi chiỊu dµi lµ a1 vµ chiỊu réng lµ b1, tạo hình chữ nhật H2 với chiều dài a2 vµ chiỊu réng lµ b2 (a1,b1,a2,b2 nhËp vµo tõ bµn phím) In hình tổng diện tích hai hình chữ nhật H1 H2
Bài 3.5: a Xây dựng lớp Mytime mô tả thông tin giờ, phút giây, lớp gồm có
các thành phần sau:
- Các thuộc tính mô tả giờ, phút, giây số nguyên
- Hm thiết lập có tham số giờ, phút giây đợc lấy giá trị ngầm định - Hàm thành phần Set(int hh, int mm, int ss) để đặt thời gian
- Hàm hiển thị thời gian theo dạng: hh:mm:ss - Khai báo toán tử >= hàm bạn lớp Mytime b Viết toán tử >= để so sánh hai đối tợng Mytime
c Viết chơng trình nhập liệu vào mảng n đối tợng kiểu Mytime Tìm in hình thời gian ln nht
Bài 3.6: a Xây dựng lớp Mydate mô tả thông tin ngày, tháng, năm, lớp gồm có
thành phần:
- Các thuộc tính mô tả ngày, tháng, năm số nguyªn
- Hàm thiết lập với ba tham số có giá trị ngầm định ngày 1, tháng 1, năm 1980 - Hàm thành phần Set(int dd, int mm, int yy) để đặt ngày, tháng, năm
- Hµm in thông tin ngày, tháng, năm theo dạng: dd-mm-yy - Khai báo toán tử >= hàm bạn líp Mydate
b Viết tốn tử >= để so sánh hai đối tợng Mydate
c Viết chơng trình nhập vào mảng n đối tợng kiểu Mydate Sắp xếp tăng dần theo thời gian in hình thời gian xếp
Bµi 3.7: a Xây dựng lớp Mydate mô tả thông tin ngày, tháng, năm, lớp gồm có
thành phần:
- Các thuộc tính mô tả ngày, tháng, năm số nguyên
- Hm thit lp với ba tham số có giá trị ngầm định ngày 1, tháng 1, năm 1980 - Hàm thành phần Set(int dd, int mm, int yy) để đặt ngày, tháng, năm
- Hàm in thông tin ngày, tháng, năm theo dạng: dd-mm-yy - Toán tử ++ để tăng ngày lên
b Viết chơng trình nhập vào đối tợng kiểu Mydate Gọi toán tử ++ để tăng ngày lên in hình thời gian sau tăng
Bài 3.8: a Xây dựng lớp PS mô tả đối tợng phân số, lớp gồm thành phần:
- C¸c thuéc tính mô tả tử số mẫu số phân sè
- Hàm thiết lập phân số lấy giá trị ngầm định phân số - Hàm thành phn nhp phõn s
- Hàm in phân số dạng ts/ms
- Khai báo hàm tự rút gọn phân số hàm bạn lớp phân số - Khai báo toán tử + hàm bạn lớp phân số
(74)- Hàm rút gän mét ph©n sè
- Tốn tử + để tính tổng phân số, kết trả phân số tối giản
c Viết chơng trình n đối tợng phân số vào từ bàn phím Tính in tổng n phân số nhập
Bài 3.9* Xây dựng lớp PS để biểu diển phân số: a Các phép toán định nghĩa cho lớp phân số:
- C¸c phÐp to¸n +, - , * , / kết phân số tối giản - Các phép toán so sánh: >, >=, <, <=, ==, !=
- Phép toán đảo dấu
- C¸c phÐp to¸n ++, , +=, -= - Hàm rút gọn phân số
- Toỏn tử >> để nhập giá trị phân số, có kiểm tra mẫu số - Toán tử << để in phân số dạng tối giản
Chú ý: Các phép tốn đợc viết theo cách:
- C¸c phÐp toán hàm thành phần lớp - Các phép toán hàm bạn lớp
b Viết chơng trình nhập vào mảng phân số thực hiện: - Tính tổng phân số mảng nhập
- Tính tích phân số mảng nhập - Tìm phân số lớn v nht
- Sắp xếp mảng phân số tăng dần Bài giải:
//phanso.cpp
#include <iostream.h> #include <math.h> #include <conio.h> #include <stdlib.h> class ps{
static void ErrorMessage(); int tu, mau;
public:
ps(int t=0,int m=1){tu=t;mau=m;}
ps(const ps &other){tu=other.tu;mau=other.mau;} friend int operator == (const ps &, const ps &); friend int operator != (const ps &, const ps &); friend int operator > (const ps &, const ps &); friend int operator >= (const ps &, const ps &); friend int operator < (const ps &, const ps &); friend int operator <= (const ps &, const ps &); friend ps operator + (const ps &, const ps &); friend ps operator - (const ps &, const ps &); friend ps operator * (const ps &, const ps &); friend ps operator / (const ps &, const ps &); friend ps toigian(const ps &);
(75)
ps operator = (const ps &c){return (*this = *thisc);} //Goi toan tu ps operator *= (const ps &c){return (*this = *this*c);} //Goi toan tu * ps operator /= (const ps &c){return (*this = *this/c);} //Goi toan tu / ps operator ++ (){return (*this = *this+1);}
ps operator (){return (*this = *this-1);}
//Dinh nghia chong cac toan tu nhap, xuat
friend ostream & operator << (ostream &out, const ps &c);
friend istream & operator >> (istream &in,ps &c); //Khong duoc cost };
/* -*/ int operator == (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau==c1.mau*c2.tu);}
/* -*/ int operator != (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau!=c1.mau*c2.tu);}
/* -*/ int operator > (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau>c1.mau*c2.tu);}
/* -*/ int operator >= (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau>=c1.mau*c2.tu);}
/* -*/ int operator < (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau<c1.mau*c2.tu);}
/* -*/ int operator <= (const ps &c1, const ps &c2)
{return (c1.tu*c2.mau<=c1.mau*c2.tu);}
/* -*/ ps operator + (const ps &c1, const ps &c2)
{return toigian(ps(c1.tu*c2.mau+c1.mau*c2.tu,c1.mau*c2.mau));} /* -*/
ps operator - (const ps &c1, const ps &c2)
{return toigian(ps(c1.tu*c2.mau-c1.mau*c2.tu,c1.mau*c2.mau));} /* -*/
ps operator * (const ps &c1, const ps &c2)
{return toigian(ps(c1.tu*c2.tu,c1.mau*c2.mau));} /* -*/ ps operator / (const ps &c1, const ps &c2){
if (c1.mau*c2.tu!=0)
return toigian(ps(c1.tu*c2.mau,c1.mau*c2.tu)); else{
ps::ErrorMessage(); return ps(0,0); }
}
/* -*/ int uscln(int x, int y){
(76)if (a==0) return 0; while (a!=b)
if (a>b) a=a-b; else
if (b>a) b=b-a; return a;
}
/* -*/ ps toigian(const ps &c){
int temp=uscln(c.tu,c.mau); if (temp!=0)
return ps(c.tu/temp,c.mau/temp); else
return ps(0,c.mau); }
/* -*/ ostream & operator << (ostream & out, const ps &c){ if (c.mau>0)
out<<c.tu<<"/"<<c.mau; else
out<<-c.tu<<"/"<<-c.mau; return out;
}
/* -*/ istream & operator >> (istream & in,ps &c){
cout<<"Tu=";in>>c.tu; do{
cout<<"Mau=";in>>c.mau; }while (c.mau==0); return in;
}
/* -*/ void ps::ErrorMessage(){
cout<<"Divide by zero !"; getch();
exit(0); }
/* -*/ void main(){
clrscr(); ps a,b,c;
cin>>a; cout<<"a="<<a<<"\n"; cout<<"++a="<<++a<<"\n"; cin>>b; cout<<"b="<<b<<"\n"; cin>>c; cout<<"c="<<c<<"\n";
(77)}
Bài 3.10: a Xây dựng lớp Complex mô tả đối tợng số phức, lớp gồm thành
phÇn:
- Các thuộc tính mơ tả phần thực phần ảo số phức - Hàm thiết lập số phức lấy giá trị ngầm định số phức
- Hàm thành phần Set(int r, int a) để đặt phần thực phần ảo số phức - Hàm in số phức dạng a+ib
- Khai b¸o to¸n tư +, toán tử - hàm bạn lớp số phøc
b Viết toán tử + toán tử - để tính tổng, hiệu số phức, kết trả số phức c Viết chơng trình nhập liệu vào từ bàn phím để tạo hai đối tợng số phức x, y Tính in hình tổng, hiệu hai số phức
Bài 3.11: a Tạo lớp Vector mô tả đối tợng vector, lớp gồm thành phần:
- Sè phÇn tư: n
- Một trỏ *v trỏ đến phần tử liệu
- Hàm thiết lập để cấp phát n vùng nhớ cho trỏ *v - Hàm thiết lập chép
- Hàm huỷ bỏ để xoá vùng nhớ đợc trỏ *v
- Hàm nhập để nhập số phần tử phần tử véc tơ - Hàm hiển thị phần tử liệu vector
- Toán tử = để gán đối tợng vector cho vector
- Khai báo toán tử + hàm bạn lớp Vector, dùng để cộng hai vector b Viết toán tử + để cộng hai vector, kết trả vector
c ViÕt ch¬ng trình nhập vào hai vector a, b In hình phần tử liệu vector a, vector b vµ vector a+b
Bài giải: Trong tập này, toán tử = đợc viết theo cách.
Cách 1: Toán tử = đuợc viết hàm kiểu void
#include<iostream.h> #include<conio.h> class vector{ private: int n; float *v; public:
vector(int size =0){ n=size;
v=new float[n]; }
vector(vector &a);
void operator =(vector &a); void nhap();
void display();
friend vector operator + (vector &a,vector &b); ~vector(){delete v;}
};
vector::vector(vector &a){ v=new float[a.n];
n=a.n;
for (int i=0;i<a.n;i++) v[i]=a.v[i];
}
(78)for (int i=0;i<n;i++){ cout<<"v["<<i<<"]="; cin>>v[i];
} }
void vector::display(){ for (int i=0;i<n;i++) cout<<v[i]<<" "; cout<<"\n";
}
void vector::operator =(vector &a){ delete v;
n=a.n;
v=new float[n];
for (int i=0;i<n;i++) v[i]=a.v[i];
}
vector operator +(vector &a, vector &b){ vector c(a.n);
for (int i=0;i<a.n;i++) c.v[i]=a.v[i]+b.v[i]; return c;
}
void main(){ clrscr(); vector x(3); x.nhap(); x.display(); vector y(3); y.nhap(); y.display(); vector z;
cout<<"\n Tong la \n"; z=x+y;
z.display(); getch(); }
- Hãy thử nghĩ xem với phơng án viết nh hàm thiết lập chép đợc gọi lần hàm huỷ bỏ đợc gọi lần đợc gọi điểm chơng trình
- Nếu tham số hình thức toán tử = toán tử + đối tợng, khơng phải tham chiếu việc gọi hàm truyền tham số thực gọi đến hàm thiết lập sao chép để truyền tham trị cho hàm làm cho chơng trình chạy chậm thời gian sao chép số lợng lớn liệu Do ngời ta thờng sử dụng tham chiếu đối tợng làm tham số hình thức hàm.
- Thứ tự thực hàm phép toán z=x+y trờng hợp x y tham chiếu cđa to¸n tư +
+ Gọi đến tốn tử +
+ Trun tham sè y, x cho to¸n tö +
+ Gọi đến hàm thiết lập lớp vector để tạo vector c + Thực cộng thành phần liệu
+ Gọi đến hàm thiết lập chép để chép liệu vector c đến vector x+y + Gọi hàm huỷ bỏ để huỷ vector c
+ Gọi đến toán tử = để gán vector x+y cho vector z
(79)#include<iostream.h> #include<conio.h> class vector{ private: int n; float *v; public:
vector(int size =0){ n=size;
v=new float[n]; }
vector(vector &a);
vector &operator =(vector &a); void nhap();
void display();
friend vector operator + (vector &a,vector &b); ~vector(){delete v;}
};
vector::vector(vector &a){ v=new float[a.n];
n=a.n;
for (int i=0;i<a.n;i++) v[i]=a.v[i];
}
void vector::nhap(){ for (int i=0;i<n;i++){ cout<<"v["<<i<<"]="; cin>>v[i];
} }
void vector::display(){ for (int i=0;i<n;i++) cout<<v[i]<<" "; cout<<"\n";
}
vector &vector::operator =(vector &a){ delete v;
n=a.n;
v=new float[n];
for (int i=0;i<n;i++) v[i]=a.v[i];
return *this; }
vector operator +(vector &a, vector &b){ vector c(a.n);
for (int i=0;i<a.n;i++) c.v[i]=a.v[i]+b.v[i]; return c; } void main(){ clrscr(); vector x(3); x.nhap(); x.display(); vector y(3); y.nhap(); y.display(); vector z;
cout<<"\n Tong la \n"; z=x+y;
(80)getch(); }
Bài 3.12: a Tạo lớp Vector mô tả đối tợng vector, lớp gồm thành phần:
- Sè phÇn tö: n
- Một trỏ *v trỏ đến phần tử liệu - Hàm thiết lập chép
- Hµm hủ bá
- Hàm nhập để nhập số phần tử phần tử véc tơ - Hàm hiển thị phần tử liệu vector
- Toán tử = để gán đối tợng vector cho vector
- Khai báo toán tử * hàm bạn lớp vector, dùng để nhân số thực k với vector
b Viết toán tử * để nhân số thực k với vector, kết trả mt vector
c Viết chơng trình nhập vào sè thùc k vµ mét vector a In mµn hình phần tử liệu vector a vector k*a
Bài 3.13*: a Xây dựng lớp matrix mơ tả đối tợng ma trận hai chiều kích thớc nxm Lớp gồm thành phần:
- Sè hµng n vµ sè cét m
- Một trỏ **data trỏ đến phần tử liệu
- Hµm thiÕt lËp chÐp - Hµm hủ bá
- Hàm nhập để nhập số hàng, số cột phần tử ma trận - Hàm hiển thị phần tử liệu ma trận
- Toán tử = để gán đối tợng ma trận cho ma trận
- Khai báo toán tử +, toán tử -, toán tử * hàm bạn lớp matrix, dùng để cộng hai ma trận, trừ hai ma trận, nhân hai ma trận
b Viết toán tử +, toán tử -, toán tử * để cộng hai ma trận, trừ hai ma trận, nhân hai ma trận, kết trả mt ma trn
c Viết chơng trình nhập vào ma trËn A, B kÝch thíc nxm In ta hình ma trận: A, B, A+B, A-B, A*B
Bài 3.14: Một danh bạ điện thoại quan chứa thông tin họ tên, a
chỉ, số điện thoại cán
a Xây dựng lớp Person gồm thành phÇn sau:
- Thuộc tính: Name, Address, Phone để mô tả thông tin danh bạ - Hàm thiết lập với tham số
- Hµm hủ bá - Hµm lÊy Name - Hµm lÊy Address - Hµm lÊy Phone
b Xây dựng lớp List để chứa danh sách cán bộ, lớp gồm có thành phần sau: - Thuộc tính maxSize mơ tả số cán tối đa
- Thuộc tính People trỏ trỏ đến Person cán - Hàm thiết lập
- Hµm hủ bá
(81)- Hàm hiển thị danh sách cán - Hàm tìm kiếm số điện thoại
Viết chơng trình cho phép nhập danh sách cán bộ, hiển thị danh sách cán bộ, tìm kiếm theo họ tên để in địa số điện thoi
Bài giải #include<iostream.h> #include<conio.h> #include<string.h> class Person{ private: char *Name; char *Address; int Phone; public:
Person(char *hoten,char *diachi,int dthoai){ Name=new char[strlen(hoten)+1]; Address=new char[strlen(diachi)+1]; strcpy(Name,hoten); strcpy(Address,diachi); Phone=dthoai; }
char *GetName(){return Name;}
char *GetAddress(){return Address;} int GetPhone(){return Phone;} void Display(){
cout<<"\n Name:"<<Name<<" Address:"<<Address<<" Phone:"<<Phone; } ~Person(){ delete Name; delete Address; } }; /* -*/ class List{ private:
Person **People; //chua danh sach can bo int maxSize; //so can bo toi da
public:
List(int max); void Add();
void Find(char *Name); void Display();
~List(); };
List::List(int max){ maxSize=max;
People = new Person*[maxSize]; }
List::~List(){
for (int i=0;i<maxSize;i++) delete People[i]; delete People; } void List::Add(){ char *Name,*Address; int Phone;
for (int i=0;i<maxSize;i++){ cout<<"Name:";cin>>Name;
cout<<"Address:";cin>>Address; cout<<"Phone:";cin>>Phone;
(82)}
void List::Find(char *name){ int index=-1;
for (int i=0;i<maxSize;i++)
if (strcmp(People[i]->GetName(),name)==0) index=i;
if (index==-1)
cout<<"\ not found !"; else{
cout<<"\n Name:"<<People[index]->GetName();
cout<<"\n Address:"<<People[index]->GetAddress(); cout<<"\n Phone:"<<People[index]->GetPhone(); }
}
void List::Display(){
for (int i=0;i<maxSize;i++) People[i]->Display();
}
/* -*/ void main(){
clrscr(); List Canbo(3); Canbo.Add(); Canbo.Display(); char name[30];
cout<<"\n Ho ten can tim:";cin>>name; Canbo.Find(name);
getch(); }
Bài 3.15: a Xây dựng lớp MatHang mô tả đối tợng mặt hàng Lớp gồm thành phần sau:
- ten: M« tả tên mặt hàng, xâu ký tự không dài 20 ký tự - soluong: mô tả số lợng mặt hàng
- giamua, giaban: Mụ t giá mua, giá bán mặt hàng số thực - nhaphang(q): để nhập thêm q số lợng hàng
- xuathang(q): để xuất q số lợng hàng
- chenhlech(): trả chênh lệch gia_ban - gia_mua
- Hàm thiết lập MatHang(char *t, int s, float m, float b) để tạo đối tợng mặt hàng với thông tin tên mặt hàng (t), số lợng (s), giá mua (m), giá bán (m)
- Định nghĩa tốn tử << cho phép in thơng tin hình đối tợng mặt hàng b Viết chơng trình khai báo mảng trỏ đối tợng (pmh) kiểu mặt hàng, cho trỏ thành phần pmh trỏ đến đối tợng thuộc MatHang Gọi hàm thành phần lớp MatHang thông qua trỏ Kết xuất đối tợng trỏ bởi pmh ra mn hỡnh
Bài giải
#include <iostream.h> #include <conio.h> #include <string.h> class MatHang{ private:
char ten[20]; int soluong;
float giamua,giaban;
//Ham thiet lap chuan dung cho lop dan xuat public:
(83)soluong=s; giamua=m; giaban=b; }
void nhaphang(int q){soluong+=q;}
void xuathang(int q){soluong=(soluong>q) ? soluong-q:0;} float chenhlech(){
return giamua-giaban; }
friend ostream & operator << (ostream &out, MatHang &mh); };
ostream & operator <<(ostream &out, MatHang &mh){ out<<"\n -"; out<<"\n Ten mat hang:"<<mh.ten;
out<<"\n So luong:"<<mh.soluong;
out<<"\n Gia mua:"<<mh.giamua<<" Gia ban:"<<mh.giaban; out<<"\n Chenh lech gia:"<<mh.chenhlech();
return out; }
/* -*/ void main(){
MatHang *pmh[3]; char ten[20]; int sl;
float giamua, giaban; for (int i=0;i<3;i++){
cout<<"\n Nhap mat hang thu "<<i; cout<<"\n Ten mat hang:";cin>>ten; cout<<" So luong:";cin>>sl;
cout<<" Gia mua:";cin>>giamua; cout<<" Gia ban:";cin>>giaban;
pmh[i]= new MatHang(ten,sl,giamua,giaban); }
for (i=0;i<3;i++) cout<<*pmh[i]; getch();
}
Bµi 3.16: a Xây dựng lớp Point mô tả điểm mặt phẳng Lớp gồm thành
phần:
- Các thuộc tính x, y mơ tả toạ độ điểm
- Hàm thiết lập có tham số với giá trị ngầm định - Hàm thiết lập chép
- Hàm display() để hiển thị toạ độ điểm mặt phẳng
- Khai báo hàm tự tính khoảng cách hai điểm bạn với lớp b Viết hàm tự tính khoảng cách điểm
c Xây dựng lớp Line gồm có thành phần: - Hai điểm A, B xác định đoạn thẳng - Hàm thiết lập đoạn thẳng hai điểm
- Hàm distance() tính chiều dài đoạn thẳng
- Hàm hiển thị toạ độ hai điểm khoảng cách chúng
d Viết chơng trình nhập vào toạ độ hai điểm A(x1,y1), B(x2, y2) Tạo đoạn thẳng xác định hai điểm A, B Hiển thị toạ độ khoảng cách đoạn thẳng
Bài 3.17: a Xây dựng lớp Point mô tả điểm mặt phẳng Lớp gồm thành
phÇn:
(84)- Hàm thiết lập có tham số với giá trị ngầm định - Hàm thiết lập chép
- Hàm display() để hiển thị toạ độ điểm mặt phẳng b Xây dựng lớp Circle gồm thành phần:
- Thuộc tính r mơ tả bán kính đờng trịn
- Hàm thiết lập đờng trịn điểm O bán kính or - Hàm hiển thị toạ độ tâm bán kính đờng trịn - Hàm area() tính diện tích đờng trịn
d Viết chơng trình nhập vào toạ độ điểm A(x,y) bán kính r Tạo đờng trịn xác định tâm A bán kính r Hiển thị toạ độ tâm, bán kính diện tích đờng trịn
Bài 3.18: a Xây dựng lớp Point mô tả điểm mặt phẳng Lớp gồm thành
phÇn:
- Các thuộc tính x, y mơ tả toạ độ điểm
- Hàm thiết lập có tham số với giá trị ngầm định
- Khai báo hàm tự tính khoảng cách hai điểm bạn với lớp - Hàm display() để hiển thị toạ độ điểm mặt phẳng
b ViÕt mét hµm tù tính khoảng cách điểm
c Xõy dựng lớp Triangle mô tả tam giác Lớp gồm có thành phần: - Ba đỉnh tam giác điểm A, B, C
- Hµm thiết lập tam giác điểm - Hàm tính chu vi cđa tam gi¸c
- Hàm hiển thị toạ độ đỉnh chu vi tam giác
d Viết chơng trình nhập vào cặp số thực (x1,y1), (x2,y2), (x3,y3) Tạo tam giác với đỉnh A(x1,y1), B(x2,y2), C(x3,y3) Hiển thị chu vi toạ độ tam giỏc
Bài 3.19: a Xây dựng lớp Point mô tả điểm mặt phẳng Lớp gồm thành
phần:
- Cỏc thuc tớnh x, y mô tả toạ độ điểm
- Hàm thiết lập có tham số với giá trị ngầm định - Hàm move(dx, dy) để tịnh tiến điểm đến toạ độ x+dx, y+dy - Hàm display() để hiển thị toạ độ điểm mặt phẳng
b Xây dựng lớp Triangle mô tả tam giác Lớp gồm có thành phần: - Ba đỉnh tam giác điểm A, B, C
- Hàm thiết lập tam giác điểm
- Hàm move(dx, dy) để tịnh tiến tam giác đến vị trí mới: A.x=A.x+dx; A.y=A.y+dy;
B.x=B.x+dx; B.y=B.y+dy;
C.x=C.x+dx; C.y=C.y+dy; - Hàm hiển thị toạ độ đỉnh tam giác
c Viết chơng trình nhập vào cặp số thực (x1,y1), (x2,y2), (x3,y3), (dx,dy) Tạo tam giác với đỉnh A(x1,y1), B(x2,y2), C(x3,y3) Tịnh tiến tam giác theo dx, dy Hiển thị toạ độ tam giác trớc sau tịnh tiến
(85)bài tập Chơng Kế thừa
Bài 4.1: a.Xây dựng lớp Date mô tả thông tin ngày, tháng, năm Lớp gồm có thành
phần:
- Các thuộc tính mô tả ngày, tháng, năm
- Hàm thiết lập có tham số lấy giá trị ngm nh l
- Hàm hiển thị thông tin ngày, tháng, năm theo dạng: dd-mm-yy
b.Xõy dựng lớp Person mô tả thông tin ngời Lớp Person đợc kế thừa từ lớp
Date bổ sung thêm thành phần:
- Name: Mô tả tên ngời, xâu không 30 ký tự - Address: Mô tả địa ngời, xâu không 40 ký tự - Phone: Mô tả số điện thoại, số nguyên
- Hàm thiết lập tham số gồm tên, ngày, tháng, năm sinh, địa chỉ, điện thoại - Hàm OutScreen() để in thông tin đối tợng Person hình
c Viết chơng trình khai báo mảng trỏ đối tợng kiểu Person, nhập liệu vào để tạo đối tợng Person Gọi hàm thành phần OutScreen() lớp Person thông qua trỏ để in liệu hỡnh
Bài 4.2: a Xây dựng lớp Mytime mô tả thông tin giờ, phút, giây Lớp gồm thành
phần:
- Các thuộc tính mô tả giờ, phút, giây
- Hm thit lp cú tham số giờ, phút giây đợc lấy giá trị ngầm định - Hàm thành phần Settime(int hh, int mm, int ss) để đặt thời gian
- Hàm hiển thị theo 24 dạng: hh:mm:ss
b Xây dựng lớp Mydate mô tả thông tin ngày, tháng, năm Lớp gồm thành phần: - Các thuộc tính mô tả ngày, tháng, năm
- Hm thiết lập có tham số lấy giá trị ngầm định
- Hàm Setdate(int dd, int mm, int yy) để đặt ngày, tháng, năm - Hàm hiển thị thông tin ngày, tháng, năm theo dạng: dd-mm-yy
c Xây dựng lớp Datetime kế thừa từ lớp Mydate Mytime để mô tả thông tin đồng thời ngày, tháng, năm, giờ, phút, giây Lớp gồm hàm thành phần:
- Hàm thiết lập ngầm định
- Hàm Setdatetime(int dd, int mm, int yy, int hh, int pp, int ss) để đặt ngày, tháng, năm, giờ, phút, giây
- Hµm in thêi gian gåm: dd-mm-yy hh: mm: ss
d Viết chơng trình nhập vào số nguyên, tạo đối tợng Datetime đặt ngày, tháng, năm, giờ, phút giây cho đối tợng Gọi hàm in thời gian i tng ó to
Bài 4.3: a Xây dựng lớp Mytime mô tả thông tin giờ, phút, giây Lớp gồm thành
phần:
- Các thuộc tính mô tả giờ, phút, giây
- Hm thiết lập có tham số giờ, phút giây đợc lấy giá trị ngầm định - Hàm display() hiển thị theo 24 dạng: hh:mm:ss
b Xây dựng lớp Mydate mô tả thông tin ngày, tháng, năm Lớp gồm thành phần: - Các thuộc tính mô tả ngày, tháng, năm
- Hm thit lập có tham số lấy giá trị ngầm định
(86)c Xây dựng lớp Myfile kế thừa từ lớp Mydate Mytime đồng thời bổ sung thêm thành phần:
- filename: Mô tả tên tệp, xâu không 255 ký tự - filesize: Mô tả kích thớc tệp, số nguyên
- Hàm thiết lập tham số (hai tham số tên tệp, kích thớc tệp, tham số ngày, tháng, năm, tham số giờ, phút, giây)
- Hàm display() in tên tệp, kích thớc thời gian dòng hình
d Vit chng trỡnh khai bỏo mảng trỏ đối tợng kiểu Myfile, nhập liệu vào để tạo đối tợng Myfile Gọi hàm thành phần display() lớp Myfile thông qua trỏ để in liệu hình
Bài 4.4: a Xây dựng lớp SV để mô tả sinh viên Khoa mt Trng
Đại học, lớp SV gồm thành phần sau:
- Lop: Mô tả lớp học sinh viên, xâu không 10 ký tự - Hoten: Mô tả họ tên sinh viên, xâu không 30 ký tự - Hàm thiết lập không tham số
- Hàm thiết lập tham sè
- Hàm display() để in thông tin SV
b Xây dựng lớp SVSP để mô tả sinh viên thuộc hệ s phạm Lớp đợc kế thừa từ lớp SV bổ sung thờm cỏc thnh phn sau:
- Dtb: Mô tả điểm trung bình sinh viên, số thực - Hocbong: Mô tả học bổng sinh viên, số nguyên - Hàm thiết lập không tham số
- Hµm thiÕt lËp tham sè
- Hàm display() để in thông tin SVSP
c Xây dựng lớp SVTC để mô tả sinh viên thuộc hệ chức Lớp đợc kế thừa từ lớp SV bổ sung thêm thành phần sau:
- Hocphi: Mô tả học phí phải nộp sinh viên, số nguyên - Hàm thiết lập không tham số
- Hàm thiết lập tham sè
- Hàm display() để in thông tin SVTC
d Xây dựng lớp SVCN để mô tả sinh viên thuộc hệ cử nhân Lớp đợc kế thừa từ hai lớp SVSP, SVTC bổ sung thêm thành phần sau:
- Hµm thiÕt lËp tham sè
- Hàm display() để in thông tin SVCN
e Viết chơng trình khai báo mảng trỏ đối tợng kiểu SVCN, nhập liệu vào để tạo đối tợng SVCN Gọi hàm thành phần display() lớp SVCN thông qua trỏ để in thông tin SVCN hình
Bµi 4.5: a Xây dựng lớp Person mô tả thông tin vỊ ngêi Líp gåm c¸c thc
tÝnh:
- Name: Mô tả tên ngời, xâu không 30 ký tự - Address: Mô tả địa ngời, xâu không 40 ký tự - Phone: Mô tả số điện thoại, s nguyờn
- Hàm thiết lập không tham số - Hµm thiÕt lËp tham sè
(87)- Salary: Mô tả lơng cán bộ, số thực - Hàm thiết lập không tham số
- Hµm thiÕt lËp tham sè
c Xây dựng lớp Manager mô tả thông tin vỊ mét ngêi qu¶n lý, líp kÕ thõa tõ líp Officer bổ sung thêm thành phần:
- Extra: Mô tả phụ cấp ngời quản lý, mét sè thùc - Hµm thiÕt lËp tham sè
- Hàm OutScreen() để in thông tin đối tợng Manager hình
d Viết chơng trình khai báo mảng trỏ đối tợng kiểu Manager, nhập liệu vào để tạo đối tợng Manager Gọi hàm thành phần OutScreen() lớp Manager thông qua trỏ để in liu mn hỡnh
Bài 4.6: a Xây dựng lớp Person mô tả thông tin ngời Líp gåm c¸c thc tÝnh:
- Name: Mơ tả tên ngời, xâu không 30 ký tự - Address: Mô tả địa ngời, xâu không 40 ký tự - Phone: Mô tả số điện thoại, số nguyên
- Hàm thiết lập không tham số - Hàm thiết lập tham sè
b. X©y dùng mét líp Officer mô tả thông cán viên chức, lớp kế thừa từ lớp Person bổ sung thêm thành phần:
- Salary: Mô tả lơng cán bộ, số thực - Hàm thiết lập không tham số
- Hàm thiết lập tham số
c. Xây dựng lớp Student mô tả thông tin sinh viên, lớp kế thừa từ lớp Person bổ sung thêm thành phần:
- Fee: Mô tả học phí sinh viên, số thực - Hàm thiết lập không tham sè
- Hµm thiÕt lËp tham sè
d X©y dùng mét líp OffStudent kÕ thõa tõ hai lớp Officer Student, lớp bổ sung thêm thành phÊn sau:
- Hµm thiÕt lËp tham sè
- Hàm OutScreen() để in thông tin đối tợng OffStudent hình
e. Viết chơng trình khai báo mảng trỏ đối tợng kiểu OffStudent, nhập liệu vào để tạo đối tợng OffStudent Gọi hàm thành phần OutScreen() lớp OffStudent thông qua trỏ để in liệu hình
Bµi lµm
#include <iostream.h> #include <conio.h> #include <string.h> class Person{
protected:
char Name[30]; char Address[40]; int Phone;
public:
(88)Person(char pName[],char pAddress[],int pPhone){ strcpy(Name,pName);
strcpy(Address,pAddress);
Phone=pPhone;
} };
/* -*/ class Officer:virtual public Person{
protected:
float Salary; public:
Officer(){}
Officer(char pName[],char pAddress[],int pPhone, float pSalary):Person(pName,pAddress,pPhone){
Salary=pSalary; };
};
/* -*/ class Student:virtual public Person{
protected: float Fee; public:
Student(){}
Student(char pName[],char pAddress[],int pPhone, float pFee):Person(pName,pAddress,pPhone){
Fee=pFee; };
};
/* -*/ class OffStudent: public Officer,public Student{ public:
OffStudent(char pName[],char pAddress[],int pPhone,float pSalary,float pFee):Person(pName,pAddress,pPhone){
Salary=pSalary; Fee=pFee;
};
void OutScreen(){
cout<<"\n Name:"<<Name;
cout<<"\n Address:"<<Address; cout<<"\n Phone:"<<Phone; cout<<"\n Salary:"<<Salary; cout<<"\n Fee:"<<Fee;
} };
/* -*/ void main(){
clrscr();
OffStudent *p[5];
(89)int Phone;
float Salary,Fee; for (int i=0;i<3;i++){
cout<<"Nhap thong tin nguoi thu "<<i+1<<"\n"; cout<<"Ho ten:";cin>>Name;
cout<<"Dia chi:";cin>>Address; cout<<"Dien thoai:";cin>>Phone; cout<<"Luong:";cin>>Salary; cout<<"Hoc phi:";cin>>Fee;
p[i]=new OffStudent(Name,Address,Phone,Salary,Fee); }
for (i=0;i<3;i++) p[i]->OutScreen(); getch();
}
Bài 4.7: a Xây dựng lớp đối tợng máy in, lớp gồm có thành phần:
+ Các thuộc tính số hiệu số lợng kho
+ Hàm nhapkho(int q) để nhập vào kho q đơn vị mặt hàng + Hàm xuatkho(int q) để xuất khỏi kho q đơn vị mặt hàng
b Xây dựng lớp máy in laser kế thừa từ lớp máy in có thêm thuộc tính dpi
c Xây dựng lớp máy in màu kế thừa từ lớp máy in có thêm thuộc tính băng màu d Xây dựng lớp máy in laser màu kế thừa từ lớp máy in laser máy in màu
e Vit chơng trình hớng đối tợng quản lý loại máy in với thủ tục: nhập, xuất in số lợng loại có kho
#include <iostream.h> #include <conio.h> #include <string.h> class mayin{
protected:
char sohieu[25]; int soluong;
//Ham thiet lap chuan dung cho lop dan xuat
public:
mayin(){};
mayin(char *s, int sl=0){strcpy(sohieu,s);soluong=sl;} void nhapkho(int sl){soluong+=sl;}
void xuatkho(int sl){soluong=(soluong>sl) ? soluong-sl:0;} void baocao(){
cout<<"May in "<<sohieu<<" ton "<<soluong<<" chiec \n"; }
};
/* -*/
//Lop ke thua ao
class laser:virtual public mayin{ protected:
int dpi;
laser(int d){dpi=d;} public:
(90)cout<<"May in Laser"<<sohieu<<" ("<<dpi<<" dpi ) ton "; cout<<soluong<<" chiec \n";
} };
/* -*/ class inmau:virtual public mayin{
protected: int bangmau;
inmau(int bm){bangmau=bm;} public:
inmau(char *s, int bm):mayin(s){bangmau=bm;} void baocao(){
cout<<"May in mau"<<sohieu<<" ("<<bangmau; cout<<" bang mau ) ton "<<soluong<<" chiec \n"; }
};
/* -*/
//Su dung tinh da ke thua
class lasermau:public laser, public inmau{ public:
lasermau(char *s, int d, int bm):mayin(s),laser(d),inmau(bm){} void baocao(){
cout<<"May in Laser mau"<<sohieu<<" ("<<dpi<<" dpi ,"; cout<<bangmau<<" bang mau ) ton "<<soluong<<" chiec \n"; }
};
/* -*/ void main(){
mayin s1("Epson"); laser s2("HP6",600); inmau s3("Apple",3);
lasermau s4("Kodak",400,3); s1.nhapkho(5);
s2.nhapkho(7); s1.xuatkho(2); s3.nhapkho(2); s2.xuatkho(3); s4.nhapkho(6); s1.baocao(); s2.baocao(); s3.baocao(); s4.baocao(); getch();
}
Bài 4.8* Một lớp đối tợng mặt hàng nói chung có hai thuộc tính Tên mặt hàng
và số l ợng kho, hai phơng thức đợc dùng lớp nhập kho xuất kho Các mặt hàng đợc phân loại chi tiết mặt hàng nhập khẩu có thêm thuộc tính thuế phơng thức tăng giảm thuế, mặt hàng đại lý có thêm thuộc tính đợc hởng hoa hồng phơng thức tăng giảm hoa hồng
Để quản lý mặt hàng cần kho cất hàng Giả sử kho cất hàng mảng quản lý tối đa đợc 100 mặt hàng Hãy viết chơng trình quản lý mặt hàng gồm chức năng: + Nhập hàng vào kho
+ XuÊt hµng khái kho
(91)#include <iostream.h> #include <conio.h> #include <string.h> class MatHang {
private:
static char TenLop[]; protected:
char Ten[25]; int SLuong; public:
MatHang(char *s, int sl=0){SLuong=sl;strcpy(Ten,s);} int LaTen(char *s){return strcmp(Ten,s)==0;}
char *TenHang(){return Ten;} void Nhap(int sl){SLuong+=sl;}
void Xuat(int sl){SLuong=(SLuong>sl) ? SLuong-sl:0;} virtual void In(){
cout<<TenLop<<" "<<Ten<<" ton "<<SLuong<<" chiec\n"; }
};
/* -*/ class MatHangNK:public MatHang{
static char TenLop[]; int Thue;
public:
MatHangNK(char *s, int t):MatHang(s){Thue=t;} void TGThue(int t){
Thue+=t;
if (Thue<0) Thue=0; }
virtual void In(){ cout<<TenLop<<"
"<<Ten<<"ton"<<SLuong<<"chiec,thue"<<Thue<<"%\n"; }
};
/* -*/ class MatHangDL:public MatHang{
static char TenLop[]; int HoaHong;
public:
MatHangDL(char *s,int h):MatHang(s){HoaHong=h;} void TGHoaHong(int h){
HoaHong+=h;
if (HoaHong<0) HoaHong=0; }
virtual void In(){
cout<<TenLop<<" "<<Ten<<"ton"<<SLuong<<"chiec,hoa hong "<<HoaHong<<"%\n";
} };
/* -*/ char MatHang::TenLop[]="Mat hang";
char MatHangNK::TenLop[]="Mat hang nhap khau"; char MatHangDL::TenLop[]="Mat hang dai ly"; /* -*/ //Lop kho hang de quan ly hang hoa
const int Max=100; class KhoHang{
(92)MatHang* TroMatHang[Max]; int SoHangDK;
public:
KhoHang(char *s, int sh=0){SoHangDK=sh;strcpy(TenKho,s);} void DangKi(MatHang *);
void NhapHang(char *, int);
void XuatHang(char *, int); void BaoCao();
~KhoHang(); };
/* -*/ void KhoHang::DangKi(MatHang *mh){ for (int i=0;i<SoHangDK;i++)
if (TroMatHang[i]->LaTen(mh->TenHang())){
cout<<"Loi dang ki: Ten mat hang "<<mh->TenHang()<<"da dang ki\n";
delete mh; return; }
if (SoHangDK==Max){
cout<<"Loi dang ki: Da het cho dang ki\n"; delete mh; return; } TroMatHang[SoHangDK++]=mh; } /* -*/
void KhoHang::NhapHang(char *ten, int sl){ for(int i=0;i<SoHangDK;i++)
if (TroMatHang[i]->LaTen(ten)){ TroMatHang[i]->Nhap(sl); return;
}
cout<<"Loi nhap hang: Ten mat hang "<<ten<<" chua dang ki \n"; }
/* -*/
void KhoHang::XuatHang(char *ten, int sl){ for(int i=0;i<SoHangDK;i++)
if (TroMatHang[i]->LaTen(ten)){ TroMatHang[i]->Xuat(sl);
return; }
cout<<"Loi xuat hang: Ten mat hang "<<ten<<" chua dang ki \n"; }
/* -*/ void KhoHang::BaoCao(){
cout<<"\n\n\n "<<"Bao cao cua kho hang "<<TenKho<<"\n\n"; cout<<"Tong so mat hang da dang ky :"<<SoHangDK<<"\n\n"; for (int i=0;i<SoHangDK;i++) TroMatHang[i]->In();
}
/* -*/ KhoHang::~KhoHang(){
(93)kho1.DangKi(new MatHang("Xich lo")); kho1.DangKi(new MatHangNK("Xe may",20)); kho1.DangKi(new MatHangDL("Xe dap",10)); kho1.DangKi(new MatHang("Xich lo")); kho1.NhapHang("Xe may",5);
kho1.NhapHang("Xe dap",3); kho1.NhapHang("O to",3); kho1.XuatHang("Xe may",1);
kho2.DangKi(new MatHang("Ti vi"));
kho2.DangKi(new MatHangNK("May tinh",10)); kho2.NhapHang("Ti vi",5);
kho2.NhapHang("May tinh",10); kho1.BaoCao();
kho2.BaoCao(); getch();
(94)bài tập Chơng Mô hình
Bài 5.1: Xây dựng mơ hình hàm swap() để hoán đổi giá trị biến Xây dựng mơ hình
hàm xếp tăng dần để xếp mảng liệu số nguyên, số thực, phân số Viết chơng trình nhập vào mảng phân số, xếp tăng dần in mảng
Bài 5.2: Xây dựng mơ hình hàm để tìm giá trị lớn mảng liệu số thực, số
nguyên, xâu ký tự Viết chơng trình nhập vào mảng số thực, in giá trị lớn mảng
#include<iostream.h> #include<conio.h> #include<string.h> template <class T> T max(T *a, int n){ T m;
m=a[0];
for (int i=0;i<n;i++) if (m<a[i]) m=a[i]; return m;
}
char *max(char *a[],int n){ char *m;
m = a[0];
for (int i=0;i<n;i++)
if (strcmp(m,a[i])<0) m=a[i]; return m;
}
/* -*/ void main(){
//tim so thuc lon nhat
int n=4; float x[10];
for (int i=0;i<n;i++){ cout<<"x["<<i<<"]="; cin>>x[i];
}
cout<<"\n Max cua so thuc :"<<max(x,n);
//Tim xau lon nhat
char *a[10];
for (i=0;i<n;i++){ cout<<"Xau "<<i<<"="; cin>>a[i];
}
for (i=0;i<n;i++)
cout<<"\n Xau "<<i<<"="<<a[i]; cout<<"\n max ="<<max(a,n); getch();
}
Bài 5.3: Xây dựng mơ hình hàm max để tìm giá trị lớn mơ hình hàm để
(95)Bài 5.4: Xây dựng mơ hình lớp mơ tả điểm có toạ độ số nguyên toạ độ số thực Trong lớp có phơng thức:
- Hàm thiết lập khơng tham số khởi tạo toạ độ điểm (0,0)
- Phơng thức move(dx, dy) dùng để tịnh tiến điểm x,y tới điểm x+dx, y+dy x, y, dx, dy số thực, số phức
- Phơng thức display(x,y) để hiển thị toạ độ điểm x, y
Viết chơng trình minh hoạ với điểm toạ độ nguyên toạ độ thực
Bài 5.5: Xây dựng mô hình hàm tính s=
i=0
n −1
a[i] víi a[i] lµ số nguyên, số thực,
phõn s Vit chng trình nhập vào mảng phân số, in tng ca phõn s ú
Bài 5.6: Xây dựng mô hình hàm tính s=
i=0
n −1
a[i] với a[i] số nguyên, số thực, số phức Viết chơng trình nhập vào mảng số phức, in tổng số phc ú
Bài 5.7* Xây dựng mô hình lớp vector theo mô hình nh sau:
template <class T, int n> class Vector{
T data[n]; // n lµ số phần tử public:
// Hàm thiết lập Vector();
Vector(Vector <T, n> &); // To¸n tư g¸n
Vector <T, n> &operator = (Vector <T, n> &); // Toán tử truy nhập phân tử thứ i
T &operator [] (int i); };
Bài 5.8* Xây dựng mô hình lớp Matrix với thành phần liệu, thành phần hàm toán tử sau:
template <class T, int n> class Matrix{
T data[n][n]; // D÷ liƯu ma trËn cã kÝch thíc n x n public:
// Hµm thiÕt lËp Matrix();
Matrix(Matrix <T, n> &); // To¸n tư g¸n
Matrix <T, n> &operator = (Matrix <T, n> &); // Hµm truy nhập phần tử Matrix
T &Cell(int i, int j); // To¸n tư céng ma trËn
Matrix <T, n> operator + (Matrix <T, n> &); // To¸n tử nhân ma trận
(96)Đề cơng «n thi
(Đề đợc tạo bài, 5/10 điểm)
I Bài tập chơng đối tợng lớp
(1)Bài 1: a Xây dựng lớp Circle mơ tả đối tuợng đờng trịn, lớp gồm có các thành phần sau:
- Thuéc tÝnh r mô tả bán kính đ-ờng tròn sè thùc.
- Hàm thiết lập không tham số đặt bán kính 0.
- Hàm thiết lập tham số đặt bán kính bằng d.
- Hµm thiÕt lËp chÐp. - Hµm tÝnh diƯn tÝch.
- Hàm in hình diện tích hình trßn.
- Khai báo tốn tử + hàm bạn của lớp đờng trịn.
b Viết tốn tử + để tính tổng diện tích hai đờng trịn.
(97)(9)Bài 1: a Xây dựng lớp Rectangle mơ tả đối tợng hình chữ nhật, lớp gồm có thành phần sau:
- Các thuộc tính mơ tả chiều dài chiều rộng số thực - Hàm thiết lập không tham số đặt cạnh
- Hàm thiết lập tham số đặt cạnh x, y - Hàm thiết lập chép
- Hµm tÝnh diƯn tÝch
- Hàm in hình diện tích hình chữ nhật - Khai báo tốn tử + hàm bạn lớp Rectangle b Viết toán tử + để tính tổng diện tích hai hình chữ nhật
c Viết chơng trình tạo hình chữ nhật H1 với chiều dài a1 chiều rộng b1, tạo hình chữ nhật H2 với chiều dài a2 chiỊu réng lµ b2 (a1,b1,a2,b2 nhËp vµo tõ bµn phÝm) In hình tổng diện tích hai hình chữ nhật H1 H2
(10)Bài 1: a Xây dựng lớp Mytime mô tả thông tin giờ, phút giây, lớp gồm
có thành phần sau:
- Các thuộc tính mô tả giờ, phút, giây số nguyên
- Hm thit lập có tham số giờ, phút giây đợc lấy giá trị ngầm định - Hàm thành phần Set(int hh, int mm, int ss) để đặt thời gian
- Hàm hiển thị thời gian theo dạng: hh:mm:ss - Khai báo toán tử > hàm bạn lớp Mytime b Viết toán tử > để so sánh hai đối tợng Mytime
c Viết chơng trình nhập liệu vào để tạo hai đối tợng t1,t2 kiểu Mytime In hình thời gian lớn
Bài 1: a Xây dựng lớp Mydate mô tả thông tin ngày, tháng, năm, lớp gồm có
thành phần:
- Các thuộc tính mô tả ngày, tháng, năm
- Hm thit lp với ba tham số có giá trị ngầm định ngày 1, tháng 1, năm 1980 - Hàm thành phần Set(int dd, int mm, int yy) để đặt ngày, tháng, nm
- Hàm in thông tin ngày, tháng, năm theo dạng: dd-mm-yy - Khai báo toán tử > hàm bạn lớp Mydate
b Vit toỏn tử > để so sánh hai đối tợng Mydate
c Viết chơng trình nhập liệu vào để tạo hai đối tợng t1,t2 kiểu Mydate In hình thời gian lớn
(7)Bài 1: a Xây dựng lớp PS mô tả đối tợng phân số, lớp gồm thành phần:
- C¸c thuéc tính mô tả tử số mẫu số phân sè
- Hàm thiết lập phân số lấy giá trị ngầm định phân số
- Hàm thành phần Set(int t, int m) để đặt tử số mẫu số phân số - Hàm in phân s dng ts/ms
- Khai báo hàm tự rút gọn phân số hàm bạn lớp phân số - Khai báo toán tử + hàm bạn cđa líp ph©n sè
(98)- Tốn tử + để tính tổng phân số, kết trả phân số tối giản
c Viết chơng trình nhập liệu vào từ bàn phím để tạo hai đối tợng phân số a, b Tính in tổng hai phân số
(6)Bài 1: a Xây dựng lớp Complex mô tả đối tợng số phức, lớp gồm thành
phÇn:
- Các thuộc tính mơ tả phần thực phần ảo số phức - Hàm thiết lập số phức lấy giá trị ngầm định số phức
- Hàm thành phần Set(int r, int a) để đặt phần thực phần ảo số phức - Hàm in số phức dạng a+ib
- Khai báo toán tử + hàm bạn lớp số phøc
b Viết tốn tử + để tính tổng số phức, kết trả số phức
c Viết chơng trình nhập liệu vào từ bàn phím để tạo hai đối tợng số phức x, y Tính in tổng hai số phức
(4)Bài 1: a Tạo lớp Vector mô tả đối tợng vector, lớp gồm thành phần:
- Sè phÇn tư: n
- Một trỏ *v trỏ đến phần tử liệu - Hàm thiết lập chép
- Hµm hủ bá
- Hàm nhập để nhập số phần tử phần tử véc tơ - Hàm hiển thị phần tử liệu vector
- Khai báo toán tử + hàm bạn lớp Vector, dùng để cộng hai vector b Viết toán tử + để cộng hai vector, kết trả mt vector
c Viết chơng trình nhập vào hai vector a, b In hình phần tử liệu vector a, vector b vector a+b
(5)Bài 1: a Tạo lớp Vector mô tả đối tợng vector, lớp gồm thành phần:
- Sè phÇn tư: n
- Một trỏ *v trỏ đến phần tử liệu - Hàm thiết lập chép
- Hµm hủ bá
- Hàm nhập để nhập số phần tử phần tử véc tơ - Hàm hiển thị phần tử liệu vector
- Khai báo toán tử * hàm bạn lớp Vector, dùng để nhân số thực k với vector
b Viết toán tử * để nhân số thực k với vector, kết trả vector
c Viết chơng trình nhập vào số thực k vector a In hình phần tử liệu vector a vector k*a
II Bài tập chơng mô hình
(2)Bi 1: Xây dựng mơ hình hàm swap() để hốn đổi giá trị biến Xây dựng mơ hình
(99)(3)Bài 1: Xây dựng mơ hình hàm để tìm giá trị lớn mảng liệu số thực, số nguyên, xâu ký tự Viết chơng trình nhập vào mảng số thực, in giá trị lớn mảng
(8)Bài 1: Xây dựng mơ hình hàm max để tìm giá trị lớn mơ hình hàm để
tìm giá trị bé mảng số thực, số nguyên, phân số Viết ch ơng trình nhập vào mảng phân số, in hình giá trị lớn bé phân số
Bài 1: Xây dựng mơ hình lớp mơ tả điểm có toạ độ số nguyên toạ độ
c¸c số thực Trong lớp có phơng thức:
- Hàm thiết lập không tham số khởi tạo toạ độ điểm (0,0)
- Phơng thức move(dx, dy) dùng để tịnh tiến điểm x,y tới điểm x+dx, y+dy x, y, dx, dy số thực, số phức
- Phơng thức display(x,y) để hiển thị toạ độ điểm x, y
Viết chơng trình minh hoạ với điểm toạ độ nguyên v to thc
(11)Bài 1 : Xây dựng mô hình hàm tính s=
i=0
n 1
a[i] với a[i] số nguyên, số
thực, phân số Viết chơng trình nhập vào mảng phân số, in tổng phân s ú
Bài 1 : Xây dựng mô hình hàm tính s=
i=0
n 1