Tải bản đầy đủ (.pdf) (16 trang)

Microsoft word lab, OOP Kỹ thuật lập trình

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (923.99 KB, 16 trang )

KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
Mục tiêu của bài tập này:







Hiểu rõ các khái niệm căn bản của hướng đối tượng.
Có thể tạo một lớp (class) và dùng lớp đó bằng cách tạo đối tượng từ lớp và gọi
phương thức của đối tượng.
Biết cách thiết kế lớp đơn giản để giải quyết bài toán.
Hiểu và sử dụng tính thừa kế
Hiểu được sơ đồ lớp cơ bản
Biết về tính đa hình (polymorphism)

Câu 1: Cho chương trình sau đây, nằm giữa “BEGIN PROGRAM” và “END PROGRAM”.
a) Chạy chương trình đó.
b) Chương trình này đó in ra những gì trên màn hình khi kết thúc thực thi. Chú ý, trên
Windows, các bạn phải chạy ở chế độ dòng lệnh, mới thấy hết các dịng chương trình
in ra? Hãy giải thích kết quả được in ra.
Ghi ra kết quả ở các dòng sau đây:
L1: ….
L2: …. (tự thêm tiếp các dịng khác)
c) Hàm ~A(): là hàm gì? Được gọi khi nào?
d) Nếu xố bỏ dịng “public:”, biên dịch lại chương trình có lỗi khơng? Vì sao?
e) Nếu thay chữ “private” thành “protected”, biên dịch lại chương trình có lỗi khơng? Vì
sao?
f) Nếu xố bỏ tồn bộ hàm khởi tạo A(). Biên dịch lại chương trình có lỗi khơng? Vì


sao?
g) Nếu xố bỏ tồn bộ hàm khởi tạo A(const A& ob). Biên dịch lại chương trình có lỗi
khơng? Vì sao? Nếu biên dịch thành cơng, chạy thì in ra những gì?
h) Nếu xố bỏ tồn bộ hàm huỷ. Biên dịch lại chương trình có lỗi khơng? Vì sao? Nếu
biên dịch thành cơng, chạy thì in ra những gì?
i) Thay vì khởi động biến m_value trên dòng khởi tạo, như “A():
m_value(123)”, có cách nào khác? Hãy thực hiện theo cách đó, biên dịch và
chạy.
----- BEGIN PROGRAM-----#include <iostream>
#include <iomanip>
using namespace std;
class A{

TRANG 1


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
private:
int m_value;
public:
A(): m_value(123){
cout << "In A(), value = " << m_value << endl;
}
A(const A& ob): m_value(ob.m_value){
cout << "In A(const A& ob), value = " << m_value << endl;
}
A(int value): m_value(value){
cout << "In A(int value), value = " << m_value << endl;
}

~A(){
cout << "In ~A(), value = " << m_value << endl;
}
};
int main(){
A ob1;
A *ptr1 = new A(246);
{
A ob2(456);
A ob3(ob1);
}
delete ptr1;
A ob4(789);
A ob5 = 357;
return 0;
};

----- END PROGRAM--------Hướng dẫn:
1) Copy chương trình, biên dịch và chạy. Lưy ý, để phải được cả những kết quả sau khi
chương trình kết thúc.
2) Chỉnh sửa từng bước theo các yêu cầu; sau đó, biên dịch, chạy nếu được, giải thích
kết quả.
Câu 2: Cho chương trình sau đây, nằm giữa “BEGIN PROGRAM” và “END PROGRAM”.
a) Hãy điền vào //(1) các dòng để khởi động giá trị m_value trong lớp X, Y, và Z với
các giá trị của thông số vx, vy, và vz tương ứng.
b) Hãy điền vào //(2) dòng lệnh để xuất 3 giá trị m_value (có 3 giá trị có tên m_value)
trong đối tượng “obj” ra màn hình, theo định dạng: vx, vy, vz.
----- BEGIN PROGRAM-----class X{
public:
int m_value;

};

TRANG 2


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
class Y: public X{
public:
int m_value;
};
class Z: public Y{
public:
Z(int vx, int vy, int vz){
//(1)
}
public:
int m_value;
};
int main(){
Z obj(1,2,3);
//(2)
return 0;
};

----- END PROGRAM--------Hướng dẫn:
1) Copy chương trình, biên dịch và chạy.
2) Để truy cập các thành viên được định nghĩa lại (overriden) thì dùng toán tử phân giải
tầm vực – xem slide bài giảng.


Câu 3: Cho chương trình sau đây, nằm giữa “BEGIN PROGRAM” và “END PROGRAM”.
a) Biên dịch chương trình có lỗi khơng? Nếu khơng lỗi thì khi chạy, chương trình in ra
gì trên màn hình?
b) Nếu thay từ khố public trong “class Z: public Y” thành protected, biên dịch lại có lỗi
khơng? Vì sao?
c) Nếu thay từ khố public trong “class Y: public X” thành protected, biên dịch lại có
lỗi khơng? Vì sao?
d) Nếu thay từ khoá public trong “lớp X” thành protected, biên dịch lại có lỗi khơng? Vì
sao?
----- BEGIN PROGRAM-----class X{
public:
void display(){
cout << "class X" << endl;
}
};
class Y: public X{
public:
void display(){

TRANG 3


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
cout << "class Y" << endl;
}
};
class Z: public Y{
public:
void display(){

cout << "class Z" << endl;
}
};
int main(){
Z obj;
obj.X::display();
obj.Y::display();
obj.Z::display();
obj.display();
return 0;

};
----- END PROGRAM--------Hướng dẫn:
1) Copy chương trình, biên dịch và chạy.
2) Thay đổi từng bước theo yêu cầu; sau đó, biên dịch và chạy nếu được. Giải thích kết
quả.

Câu 4: Cho chương trình sau đây, nằm giữa “BEGIN PROGRAM” và “END PROGRAM”.
a) Biên dịch, chạy, và giải thích kết quả
b) Thêm từ khố “virtual” vào chổ /*(1)*/ (trước phương thức display trong lớp X).
Biên dịch, chạy, và giải thích kết quả
----- BEGIN PROGRAM-----#include <iostream>
using namespace std;
class X{
public:
/*(1)*/ void display(){
cout << "Type of \"this\" object is: Class X" << endl;
}
};
class Y: public X{

public:
void display(){
cout << "Type of \"this\" object is: Class Y" << endl;
}
};
class Z: public Y{
public:

TRANG 4


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
void display(){
cout << "Type of \"this\" object is: Class Z" << endl;
}
};
int main(){
cout << "Call method via NON-POINTER variable - CASE I:" << endl;
X x;
Y y;
Z z;
x.display();
y.display();
z.display();
/////////////////
cout << " Call method via NON-POINTER variable - CASE II:" << endl;
X x1, x2, x3;
Y y2;
Z z3;

x2 = y2; x3 = z3; //ATTENTION
x1.display();
x2.display();
x3.display();
/////////////////
cout << " Call method via POINTER variable - CASE I:" << endl;
X *px = new X();
Y *py = new Y();
Z *pz = new Z();
px->display();
py->display();
pz->display();
delete px;
delete py;
delete pz;
/////////////////
cout << " Call method via POINTER variable - CASE II:" << endl;
X *px1 = new X();
X *px2 = new Y(); //ATTENTION
X *px3 = new Z(); //ATTENTION
px1->display();
px2->display();
px3->display();
delete px1;
delete px2;
delete px3;
return 0;
};

----- END PROGRAM---------


TRANG 5


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
Hướng dẫn:
1) Copy chương trình, biên dịch và chạy.
2) Gọi phương thức không thông qua con trỏ: phép gán đối tượng của lớp con con
vào đối tượng của lớp cha (như dòng: x2 = y2; x3 = z3;) là cho phép. Vì đối
tượng của lớp con chứa trong đó đối tượng có kiểu lớp cha. Nhưng ngược lại thì
khơng được.
3) Gọi phương thức thông qua con trỏ: con trỏ đến đối tượng lớp cha luôn luôn gán
được cho con trỏ đến đối tượng của lớp cha, như dòng: X *px2 = new Y(); X *px3 =
new Z();. Phép gán này có ý nghĩa trong tính đa hình – xem kết quả của chương
trình, sự khác nhau ở câu a) và b).
Câu 5: Cho chương trình sau đây, nằm giữa “BEGIN PROGRAM” và “END PROGRAM”.
a) Thêm vào lớp Y là lớp con của lớp X. Định nghĩa lại (override) phương thức display
trong X, sao cho bên ngoài lớp Y vẫn gọi được – như dòng: “y.display();“
trong hàm main
b) Thêm vào lớp Z là lớp con của lớp Y. Định nghĩa lại (override) phương thức display
thừa kế được từ lớp Y, sao cho bên ngồi lớp Z khơng thể dùng phương thức display
được nữa – như dòng: “z.display();“ trong hàm main. Sinh viên phải thực hiện
bằng 2 cách khác nhau:
----- BEGIN PROGRAM-----#include <iostream>
using namespace std;
class X{
public:
/*(1)*/ void display(){
cout << "Type of \"this\" object is: Class X" << endl;

}
};
int main(){
X x;
Y y;
Z z;
x.display(); //OK
y.display(); //OK
z.display(); //Error during compilation
return 0;
};

----- END PROGRAM---------

TRANG 6


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
Hướng dẫn:
Câu 5.b) Cho hai cách phổ che dấu phương thức của lớp cha:
1) Dùng thừa kế kiểu protected hay private. Ví dụ: “class Z: protected Y”
2) Vẫn dùng thừa kế kiểu public, nhưng hàm bị định nghĩa lại có tính private hay
protected trong lớp Z.

Câu 6: Một đối tượng kiểu Date lưu thông tin về ngày, tháng, và năm. Hãy tạo ra kiểu Date
để người dùng (người lập trình) có thể chạy được đoạn chương trình sau. Các dịng được giải
thích như sau:




Dịng 2: Chèn phần header của lớp Date mà sinh viên tạo ra.



Dịng 8: Tạo hai đối tượng có kiểu Date, giá trị ban đầu của ngày, tháng, và năm gán
giá trị khơng hợp lệ nào đó; ví dụ: year = -1. Tốt nhất: sinh viên lấy ngày của hệ
thống gán cho các thành viên của lớp Date; do đó, có thể cho phép người dùng tạo
ngày chứa ngày hiện tại dễ dàng.



Dịng 10 và 12: Lớp Date phải hỗ trợ nhập ngày bằng toán tử chèn >>. Người dùng
có thể nhập ngày bằng cách gõ: 5/2/2017 và ENTER.
TRANG 7


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng


Dịng 14 và 15: Lớp Date phải hỗ trợ nhập ngày bằng toán tử chèn << cho các đối
tượng Date. Ví dụ, với ngày nhập ở trên thì in ra: 05/02/2017 (nghĩa là thêm số 0 nếu
chưa đủ 2 ký tự số).



Dịng 16: Lớp Date phải hỗ trợ tốn tử so sánh < giữa hai đối tượng Date.




Dịng 18: Lớp Date phải hỗ trợ tạo đối tượng Date bằng cách truyền ngày, tháng và
năm vào thông số của hàm khởi tạo.



Dịng 19: Lớp Date phải hỗ trợ phương thức toString. Phương thức này đổi đối tượng
sang chuỗi. Cụ thể, dòng 19 sẽ in ra: 25/05/2017.

Hướng dẫn:
Với các toán tử: xem slide bài giảng và ví dụ cho ma trận để biết cách khai báo
prototype của nó.

Câu 7: Xây dựng một kiểu dữ liệu có tên MyString. MyString cung cấp những cách giúp
người lập trình dễ dàng thao tác được với dữ liệu dạng chuỗi, như tạo chuỗi, nối chuỗi, in
chuỗi, nhập chuỗi, tìm chuỗi con, v.v. Sinh viên phải quản lý dữ liệu chuỗi bằng con trỏ và
cấp phát bộ nhớ động.
Lưu ý: Khi xây dựng lớp MyString, các sinh viên không được sử dụng thư viện <string>,
chỉ được sử dụng các thư viện sau: <iostream>, <string.h> (hoặc <memory>).
(a) Nếu dùng <string.h>: chỉ được dùng hai hàm strlen và strcpy.
(b) Nếu dùng <memcpy>: tự hiện thực lại hàm có chức năng như strlen và dùng hàm
memcpy thay cho strcpy.
Lớp MyString phải hỗ trợ những phương thức, hàm khởi tạo, hàm huỷ, và các tốn tử để
người dùng nó có thể thực hiện đoạn chương trình sau:

Các dịng lệnh trong đó được giải thích như sau:
TRANG 8


KỸ THUẬT LẬP TRÌNH

Nội dung về Lập trình hướng đối tượng


Dịng 37: Hỗ trợ tạo đối tượng MyString với một hằng chuỗi (literal string) truyền
vào.



Dịng 38: Hỗ trợ hàm khởi tạo để khởi gán với một chuỗi truyền vào bên phải dấu
“=”.



Dịng 39: Hỗ trợ nối các chuỗi.



Dịng 40: có thể xuất đối tượng chuỗi ra màn hình bằng tốn tử <<



Dịng 41: Hỗ trợ tạo chuỗi rỗng



Dịng 42: Hỗ trợ phép gán.



Dịng 45: Hỗ trợ nhập chuỗi từ bàn phím bằng phép gán.




Dịng 46: Hỗ trợ phép tốn nối chuỗi bằng toán tử +=

Hướng dẫn:
(1) Với yêu cầu dùng bộ nhớ cấp phát động. Dữ liệu chuỗi có thể khai báo như sau:
char* m_pchar;
(2) Lưu ý: với chuỗi thì khơng cần lưu thêm số character. Vì, chuỗi ln ln kết thúc
bằng số 0 (‘\0’).
(3) Một khi lớp có biến thành viên cấp phát động thì khn mẫu lập sẽ thường (ln ln)
có các bước sau:


Xin cấp bộ nhớ bằng “new” trong hàm khởi tạo (constructor).



Huỷ bộ nhớ xin ở hàm khởi tạo trong hàm huỷ (destructor), bằng lệnh delete.

Phải có hàm khởi tạo copy (copy assignment) và tốn tử gán (=, copy assignment).
Hai phương thức này cần xin bộ nhớ mới và copy dữ liệu từ đối tượng truyền vào.
Nếu khơng có hai hàm này, thực thi sẽ có lỗi khi nhiều hơn 1 đối tượng cùng sở
hữu dữ liệu. Mỗi đối tượng lại delete riêng; do đó, huỷ nhiều lần à có lỗi.
(4) Các tốn tử khác, xem slide bài giảng cho trường hợp Ma trận.


Câu 8: (Kết quả của câu này sẽ được dùng cho câu kế tiếp).
Giả sử các bạn cần phát triển một chương trình liên quan đến vẽ các đối tượng hình học 2D
và 3D. Ứng dụng đó chắc chắn liên quan đến hai loại đối tượng cơ bản đó là điểm và véc-tơ

trong không gian 2 chiều (3D xét sau).
Yêu cầu: phát triển 2 lớp “Point2D” và “Vector2D”. Thiết kế hai lớp sao cho thật thuận tiện.
Source cơ bản cho câu này đã được đính kèm. Các sinh viên có nhiệm vụ:
(a) Hiện thực các phương thức nếu nó chưa đầy đủ (comment bằng chữ TODO)
TRANG 9


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
(b) Viết chương trình chính (main) để tạo ra các đối tượng và tính tốn với các đối tượng
nay nhằm kiểm tra bản hiện thực của mình. Cũng có nghĩa là làm “test-case” cho hiện
thực của hình.
Hướng dẫn:
Thuộc tính và phương thức của hai lớp “Point2D” và “Vector2D” được thiết kế theo gợi ý
như sau. Kết quả thiết kế có thể xem Hình 1.

Hình 1: Thiết kế cho kiểu Point2D và Vector2D.
TRANG 10


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
(I) Thuộc tính:
Lớp “Point2D” và “Vector2D” đều có 2 biến thành viên lưu trữ toạ x và y. Lớp
Point2D có thể có thêm biến “radius”, biến này lưu trữ bán kính của hình trịn khi điểm
được hiển thị trên màn hình. Biến này dùng chung cho mọi đối tượng kiểu Point2D, do
đó, nó được thiết kế để có tính “static”. Ở bài tập này, biến này phục vụ mục đích giúp
sinh viên hiểu được biến có tính “static” là gì? Trong Hình 1, nó được khởi gán là 1.5f
(milimeters)
(II) Phương thức:

(a) Hàm khởi tạo: Hàm khởi tạo giúp cho việc tạo các đối tượng kiểu “Point2D” và
“Vector2D” dễ dàng. Quá trình thiết kế cần cân nhắc cẩn thận.
Hàm khởi tạo cho lớp Point2D:
Cho phép tạo đối tượng và khởi gán giá trị toạ độ x và y à có hai thơng số x và
y tương ứng.



Khơng cần hàm khởi tạo copy vì hiện thực mặc định C++ là đủ - nó copy từng
thuộc tính cho nhau. Ở đây x và y là các số thực, không phải con trỏ, nên việc
copy như vậy vẫn làm việc tốt. Tương tự, phép gán copy (copy assignment)
cũng không cần thiết.
Hàm khởi tạo cho lớp Vector2D:


Hàm khởi tạo có hai thơng số x và y được đưa vào với lý do giống như lớp
Point2D.



Nên có hàm khởi tạo chấp nhận hai điểm là “head” và “tail” (là điểm đầu và
cuối của một véc-tơ) và nó tính toạ độ x và y từ hai điểm này. Trong toán học,
véc-tơ đi từ “head” đến “tail” bằng hiệu số: “tail” – “head”, nghĩa là trừ các tọa
độ x của “tail” cho toạ độ x của “head”, tương tự cho toạ độ y.
(b) Hàm huỷ: Không cần thiết với hai lớp này.
(c) Các phương thức khác:





Với lớp Point2D, nên bổ sung hai phương thức “distanceAB” để tính khoảng
cách Euclid từ điểm A đến điểm B, được truyền vào. Khi gọi phương thức này
không cần tham khảo đến bất kỳ đối tượng Point2D chứa nó; do đó, nó nên
được thiết kế với tính “static”.



Tương tự, phương thức “vectorAB” cho lớp Point2D để trả véc-tơ từ điểm A
đến điểm B. Nó cũng là phương thức có tính “static”.



Lớp Vector2D nên có phương thức: dot và ortho, như giải thích sau



Phương thức “dot”: cho phép tính tích vơ hướng của hai véc-tơ. Hai véc-tơ có
toạ độ [a b] và [c d], tích vơ hướng là một số bằng (a*c + b*d). Trong toán
TRANG 11


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
học, nếu tích vơ hướng bằng 0, nghĩa là hai véc-tơ vng góc (cịn gọi trực
giao). Do đó, để kiểm tra hai véc-tơ có vng góc, thì tính tích vơ hướng và
kiểm tra với 0. Hàm này rất hữu ích để kiểm tra xem một hình có là hình chữ
nhật hay hình vng (ở Câu 9).


Phương thức “ortho”: kiểm tra xem hai véc-tơ có vng góc, dùng phương

thức “dot” đã nói trên.

Sinh viên nên bổ sung hai phương thức dot và ortho có tính static, chúng
nhận hai véc-tơ đầu vào.
(d) Các tốn tử liên quan đến điểm và véc-tơ:
Trong mơn học Hình học giải tích (bậc trung học) cho biết, có các phép tốn sau đây
liên quan đến điểm và véc-tơ:




[Điểm A] + [véc-tơ V] à cho ra [điểm B]: dời A theo véc-tơ V ta được B (tịnh
tiến)



[Điểm A] – [Điểm B] à cho ra [véc-tơ V]: véc-tơ V đi từ B (đầu véc-tơ) đến A
(ngọn véc-tơ); lưu ý: khơng phải từ A đến B. Phép trừ có nghĩa là trừ các toạ độ
với nhau.



[Số thực F] * [véc-tơ V] à cho ra [véc-tơ T]: nhân số thực F với từng thành
phần x và y của véc-tơ (co/giản véc-tơ V để được T). Toán tử này phải được bổ
sung như một tốn tử khơng phải thành viên của lớp Vector2D; vì tốn hạng
bên phải là F khơng phải kiểu Vector2D.



[véc-tơ V] * [Số thực F] à cho ra [véc-tơ T]: Tương tự như trên, tốn hạng bên

trái có kiểu Vector2D; do đó, có thể đưa tốn tử này như là thành viên của lớp
Vector2D.



[Véc-tơ V1] + [Véc-tơ V2] à cho ra [véc-tơ T], theo quy tắc cộng véc-tơ;
nghĩa là, cộng các thành phần x và y của các véc-tơ với nhau.



Phép trừ véc-tơ là tương tự phép tốn +.

Câu 9: (Câu này sử dụng kết quả của Câu 6)
Giả sử các bạn cần phát triển một chương trình liên quan đến vẽ các đối tượng hình học 2D
và 3D. Ngồi hai loại đối tượng cơ bản đó là điểm và véc-tơ trong không gian 2 chiều (3D
xét sau), chương trình cần xử lý với các đối tượng khác như Đa giác, Tam giác, Tứ giác,
Hình chữ nhật, và Hình vuông. Bài tập này bỏ qua các đối tượng như tứ giác và các hình tứ
giác khác dẫn ra từ nó, để cho đơn giản hơn.
Yêu cầu:
TRANG 12


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
(a) Chuyển sang mã C++ cho các lớp được thiết kế như Hình vẽ 2, và được giải thích ở
các phần sau đây. Mã C++ cho các lớp Point2D, Vector2D, và TwoDShape đã được
cho sẵn đi kèm tài liệu này.
(b) Hiện thực các hàm khởi tạo & hàm huỷ của các lớp sau:



Hàm khởi của Triangle, Rectangle, và Square: thêm lần lượt các đỉnh
A,B,C, và D vào danh sách vertexList – thừa kế được từ TwoDShape.
Trường hợp của Triangle thì chỉ A, B, và C. Xem “chú giải” đi kèm Hình 2.

Với Rectangle và Square có hàm khởi tạo nhận 2 đỉnh là LT (left-top) và RB
(right-bottom). Hàm này sẽ từ LT và RB tính ra 4 đỉnh của Rectangle hay
Square và thêm 4 đỉnh đó vào vertexList.
(c) Định nghĩa lại (overriding) các phương thức thừa kế được từ lớp “TwoDShape” cho
tất cả các lớp con dẫn ra từ nó, nếu thấy cần thiết (yêu cầu thiết kế lớp từ sinh
viên). Các phương thức đó là:




getArea: tính diện tích của loại hình tương ứng, và trả về. getArea của lớp
TwoDShape trả về 0. Nếu dùng polymorphism thì đây là “abstract method”.
Lưu ý: chỉ định nghĩa lại với các lớp con của “TwoDShape” khi thấy cần thiết
(bao gồm việc dễ cho tính diện tích).



getPerimeter: tính chu vi của loại hình tương ứng, và trả về. Nếu dùng
polymorphism thì đây là “abstract method”. Lưu ý: chỉ định nghĩa lại với các
lớp con của “TwoDShape” khi thấy cần thiết (bao gồm việc dễ cho tính chu
vi).



draw: ý nghĩa của hàm này là: nó sẽ vẽ các đối tượng tương ứng chứa nó (đối
tượng “*this”) lên màn hình. Tuy nhiên, mơn học này chưa đủ kiến thức để

vẽ. Do đó, hàm này sẽ in danh sách các đỉnh (dùng cout) của các đối tượng ra
màn hình. Ngồi danh sách đỉnh, sinh viên có thể chọn và in ra bất kỳ thơng
tin gì của đối tượng cũng được. Nếu dùng polymorphism thì đây là “abstract
method”.



addVertex: thêm đỉnh được truyền bởi thông số vào danh sách các đỉnh của
đối tượng kiểu “TwoDShape”. Danh sách này được triển khai trong mã nguồn
là một đối tượng kiểu “vector” (thư viện <vector>), có tên là “vertexList” –
xem Hình 2.



isConvex: kiểm tra xem danh sách đỉnh trong vertexList có tạo thành một đa
giác lồi hay không? Trong trường hợp đa giác khơng lồi, hàm getArea có thể

TRANG 13


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng
trả về 0. Giải thuật kiểm tra tính lồi, các sinh viên có thể tham khảo bài trả lời
của “Jason S” trong link ở footnote 1.
(d) Định nghĩa phương thức addVertex trong các lớp như Triangle, Rectangle, và
Square, và đổi ln tính khả kiến của nó từ public sang private – nhằm che khơng
cho bên ngồi gọi addVertex trên các đối tượng kiểu Triangle, Rectangle, và
Square được. Xem phần hướng dẫn sau.

Hình 2: Thiết kế cho các đối tượng hình học 2D cơ bản. Lớp Point2D và Vector2D có chi

tiết ở Hình 1.
Một số chú giải cho Hình 2:

1



Dấu +: cho biết các phương thức hay thuộc tính có tính public.



Mũi tên to: cho biết sự thừa kế. Ví dụ: lớp Square thừa kế lớp Rectangle; đọc là
“Square is-a Rectangle”.

/>TRANG 14


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng


Mũi tên mảnh nối lớp “TwoDShape” và lớp “Point2D” cho biết: một đối tượng kiểu
TwoDShape có chứa kèm bên trong (như đối tượng Point2D chứa x và y – xem Hình
1) một danh sách có tên “vertexList”. Danh sách chứa các đỉnh của một hình trong
khơng gian 2 chiều. Mỗi đỉnh có kiểu là Point2D. Do đó, “vertexList” là danh sách
mà mỗi phần tử của nó là đối tượng kiểu Point2D. Trong Code C++ gửi kèm,
vertexList là một vector (của thư viện <vector>, #include <vector>), hãy xem
code kèm theo.

Hướng dẫn:

Thuộc tính và phương thức của các lớp được thiết kế theo gợi ý như sau. Kết quả thiết kế có
thể xem Hình 2.
(I) Thuộc tính:
Thuộc tính của lớp TwoDShape là vertexList, như giải thích trên.
(II) Phương thức:
(a) Hàm khởi tạo:
Lớp TwoDShape:
• Dùng hàm khởi tạo mặc nhiên là đủ.
Lớp Triangle:
• Nên có hàm khởi tạo 3 thơng số để đặt tả 3 đỉnh của một tam giác.
Lớp Rectangle và Square:


Nên có hàm khởi tạo 4 thơng số để đặt tả 4 đỉnh của một hình chữ nhật hoặc
hình vng. Hàm khởi tạo này gọi addVertex để thêm từng đỉnh vào danh
sách vertexList trong TwoDShape. Với Rectangle và Square có hàm khởi tạo
nhận 2 đỉnh là LT (left-top) và RB (right-bottom). LT là đỉnh góc trên trên và
bên trái của hình, cịn RB là đỉnh góc dưới bên phải. Hàm này sẽ từ LT và
RB tính ra 4 đỉnh của Rectangle hay Square và thêm 4 đỉnh đó vào
vertexList.

Tuy nhiên khác khác với tam giác, 4 đỉnh nhập vào nếu không tạo thành hình
chữ nhật hoặc hình vng thì hàm khởi tạo báo lỗi. Tốt nhất là nên dùng
ngoại lệ (exception, try-catch), nhưng sinh viên chưa học. Do đó, có thể lờ
qua việc kiểm tra; giả sử nếu đã truyền vào thì 4 đỉnh đã thỗ mãn điều kiện
của hình chữ nhật hoặc hình vng – tuỳ lớp.
(b) Hàm khởi tạo: không cần hàm huỷ ở bài tập này. Lý do, danh sách đỉnh trong vector
cũng chứa đối tượng thay cho con trỏ.
(c) Phương thức khác:



TRANG 15


KỸ THUẬT LẬP TRÌNH
Nội dung về Lập trình hướng đối tượng


Theo Hình 2: các lớp sau đều thừa kế phương thức addVertex (có tính
public) từ lớp TwoDShape; đó là các lớp: Polygon, Triangle, Rectangle, và
Square. Với lớp Polygon là hợp lý; vì, addVertex giúp cho người lập trình
thêm từng đỉnh vào đa giác (có nhiều đỉnh). Tuy vậy, với các lớp cịn lại
Triangle (có đúng 3 đỉnh), Rectangle và Square phải có đúng 4 đỉnh. Do đó,
addVertex thừa kế được và cho bên ngoài dùng được là một vấn đề với các
lớp này. Các lớp Triangle, Rectangle, và Square phải che hàm này đi – khơng
để bên ngồi dùng được. Bằng cách nào?
o Định nghĩa là hàm này (override), nhưng đổi ln tính khả kiến của nó
từ public sang private. Có nghĩa là đặt hàm addVertex được định nghĩa
lại đó tại vị trí mà private có ảnh hưởng.
o Bản thân hàm định nghĩa lại này có thể để trống (empty), hoặc gọi lại
addVertex của lớp TwoDShape.

TRANG 16



×