1. Trang chủ
  2. » Luận Văn - Báo Cáo

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

16 6 0

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 16
Dung lượng 0,9 MB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

Microsoft Word Lab, OOP docx KỸ THUẬT LẬP TRÌNH Nội dung về Lập trình hướng đối tượng TRANG 1 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 P.

Trang 1

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 xoá 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 xoá bỏ toà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 xoá bỏ toàn bộ hàm khởi tạo A(constA& 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 xoá bỏ toà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 {

Trang 2

private:

int m_value ;

public:

A (): m_value ( 123 ){

cout << "In A(), value << m_value << endl;

}

A const & 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;

}

~ (){

cout << "In ~A(), value << m_value << endl;

}

};

int main(){

A ob1;

A *ptr1 new ( 246 );

{

A ob2( 456 );

A ob3(ob1);

}

delete ptr1;

A ob4( 789 );

A ob5 = 357;

return ;

};

- END PROGRAM -

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 {

public:

int m_value ;

};

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ả

Trang 3

class : public {

public:

int m_value ;

};

class : public {

public:

Z int vx, int vy, int vz){

//(1)

}

public:

int m_value ;

};

int main(){

Z obj( 1 2 3 );

//(2)

return ;

};

- END PROGRAM -

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ừ khoá public trong “classZ:publicY” thành protected, biên dịch lại có lỗi không? Vì sao?

c) Nếu thay từ khoá 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 {

public:

void display(){

cout << "class X" << endl;

}

};

class : public {

public:

void display(){

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

Trang 4

cout << "class Y" << endl;

}

};

class : public {

public:

void display(){

cout << "class Z" << endl;

}

};

int main(){

Z obj;

obj X ::display();

obj Y ::display();

obj Z ::display();

obj.display();

return ;

};

- END PROGRAM -

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ừ khoá “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 {

public:

/*(1)*/ void display(){

cout << "Type of \"this\" object is: Class X" << endl;

}

};

class : public {

public:

void display(){

cout << "Type of \"this\" object is: Class Y" << endl;

}

};

class : public {

public:

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ả

Trang 5

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

Y *py new ();

Z *pz new ();

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 *px2 new (); //ATTENTION

X *px3 new (); //ATTENTION

px1->display();

px2->display();

px3->display();

delete px1;

delete px2;

delete px3;

return ;

};

- END PROGRAM -

Trang 6

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 ngoà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 {

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 ;

};

- END PROGRAM -

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 = newY(); X *px3 =

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

Trang 7

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

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

Trang 8

• 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ợ toá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

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 toá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:

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ó

Trang 9

• 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 toá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 toán nối chuỗi bằng toán tử +=

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)

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 luôn luôn 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ì khuôn mẫu lập sẽ thường (luôn luôn)

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à toá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 toán tử khác, xem slide bài giảng cho trường hợp Ma trận

Trang 10

(b) Viết chương trình chính (main) để tạo ra các đối tượng và tính toá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 11

(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 12

học, nếu tích vô hướng bằng 0, nghĩa là hai véc-tơ vuông góc (còn gọi trực giao) Do đó, để kiểm tra hai véc-tơ có vuông 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 vuông (ở Câu 9)

• Phương thức “ortho”: kiểm tra xem hai véc-tơ có vuông 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 toá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 toá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 toán tử không phải thành viên của lớp Vector2D; vì toá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, toán hạng bên

trái có kiểu Vector2D; do đó, có thể đưa toá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 toá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 Ngoà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:

Ngày đăng: 29/05/2022, 13:47

HÌNH ẢNH LIÊN QUAN

như sau. Kết quả thiết kế có thể xem Hình 1. - Microsoft word   lab, OOP Kỹ thuật lập trình
nh ư sau. Kết quả thiết kế có thể xem Hình 1 (Trang 10)
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 - Microsoft word   lab, OOP Kỹ thuật lập trình
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 (Trang 14)
w