1. Trang chủ
  2. » Kỹ Thuật - Công Nghệ

LTHDT-Ch01-Lop [Compatibility Mode] OTTN

118 14 1

Đ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

caùch keát hôïp döõ lieäu vaø phaàn thuû tuïc xöû lyù döõ lieäu vaøo trong moät thöïc theå duy nhaát, heä thoáng trôû thaønh moät sô ñoà phaân caáp duy nhaát caùc lôùp ñoái töôïng.... [r]

(1)

Lập Trình Hướng Đối Tượng Lập Trình Hướng Đối Tượng Lập Trình Hướng Đối Tượng Lập Trình Hướng Đối Tượng

(2)

Chương 1 Chương 1

(3)

Giới thiệu Giới thiệu

 Phân tích thiết kế lập trình theo hướng đối tượng sinh sau đẻ

muộn chứng tỏ ưu điểm vượt trội so với cách tiếp cận cổ điển

 Trong lãnh vực phân tích thiết kế hệ thống, hướng tiếp cận

mẻ thu hút nhiều nhà nghiên cứu tên tuổi Nhiều kiểu mẫu, phương pháp luận, mô hình phân tích đưa với mức độ thành công khác

Ta nghiên cứu phương hướng phân tích theo quan điểm

 Ta nghiên cứu phương hướng phân tích theo quan điểm

(4)

Phương pháp phân tích mô hình Phương pháp phân tích mô hình

 Phân tích dựa sở mơ hình hóa đối tượng

trong giới thực

 Dùng mơ hình để xây dựng thiết kế không phụ

thuộc ngôn ngữ tổ chức xung quanh đối tượng

 So với cách tổ chức cổ điển, mơ hình hố thiết kế

(5)

Phương pháp phân tích mô hình Phương pháp phân tích mô hình

 Các khái niệm giới thực mơ hình hố

bằng ký hiệu đồ hoạ mô tả đối tượng chúng (cấu trúc liệu hành vi) độc lập với ngôn ngữ

 Các khái niệm ký hiệu dùng thống

nhất suốt trình phát triển hệ thống từ phân tích,

thiết cài đặt mà khơng cần thay đổi qua giai đoạn số phương pháp luận khác

đoạn số phương pháp luận khác

 Không quan tâm đến chi tiết cài đặt giai đoạn

(6)

Phương pháp phân tích mô hình Phương pháp phân tích mô hình

 Các khái niệm liên quan đến máy tính đưa

ở bước mã hóa sau cùng, nhờ giữ uyển

(7)

Phương pháp luận hướng đối tượng Phương pháp luận hướng đối tượng

 Mơ hình hóa thiết kế theo hướng đối tượng lối

suy nghĩ vấn đề cần giải dùng mơ hình tổ chức xung quanh khái niệm giới thực

 Trong hệ thống thông tin hướng đối tượng, thứ,

hay thứ, quan điểm đối tượng

hay thứ, quan điểm đối tượng

 Mỗi đối tượng kết hợp hai thành phần đặc

(8)

Phương pháp luận hướng đối tượng Phương pháp luận hướng đối tượng

 Phương pháp luận theo quan điểm J.Rumbaugh bao

gồm xây dựng mơ hình hệ thống lãnh vực ứng dụng thêm chi tiết cài đặt trình thiết kế hệ thống

 Các ký hiệu đồ họa sử dụng để biểu diễn khái

niệm hướng đối tượng niệm hướng đối tượng

 Cách tiếp cận gọi kỹ thuật thiết kế mô

(9)

Phương pháp luận hướng đối tượng Phương pháp luận hướng đối tượng

 Kỹ thuật mơ hình hố OMT bao gồm bước:

Phân tích Thiết kế hệ thống

Thiết keá

(10)

Các khái niệm hướng đối tượng Các khái niệm hướng đối tượng

 Trừu tượng hố :

• Nhấn mạnh vào khía cạnh cốt yếu vốn có thực thể

và bỏ qua tính chất riêng biệt

• Sử dụng trừu tượng hố phân tích có nghĩa làm việc với

các khái niệm lãnh vực ứng dụng bỏ qua chi tiết cài đặt

• Hầu hết ngơn ngữ lập trình đại hổ trợ trừu tượng • Hầu hết ngơn ngữ lập trình đại hổ trợ trừu tượng

hố Nhưng trừu tượng hóa tận dụng tiếp cận đối tượng với tính kế thừa (inheritance) tính đa dạng

(11)

Các khái niệm hướng đối tượng Các khái niệm hướng đối tượng

 Tính đóng gói :

• Tách rời khía cạnh giao diện với bên đối tượng

với chi tiết cài đặt bên

• Tính đóng gói ngăn chặn khả chương trình trở nên

quá phụ thuộc lẫn dẫn tới hậu thay đổi nhỏ ảnh hưởng lớn đến tồn hệ thống

• Trong tiếp cận O.O khả kết hợp liệu hành vi • Trong tiếp cận O.O khả kết hợp liệu hành vi

(12)

Các khái niệm hướng đối tượng Các khái niệm hướng đối tượng

 Kết hợp liệu hành vi:

• Trong cách tiếp cận thủ tục cổ điển, hệ thống xây dựng

trên hai sơ đồ phân cấp chằng chịt: sơ đồ phân cấp liệu sơ đồ phân cấp thủ tục, liên hệ loại liệu thủ tục xử lý liệu mờ nhạt, dẫn đến khó khăn

trong việc sửa chữa, nâng cấp tương lai

• Cách tiếp cận O.O loại bỏ nhược điểm kể • Cách tiếp cận O.O loại bỏ nhược điểm kể

(13)

Các khái niệm hướng đối tượng Các khái niệm hướng đối tượng

Sơ đồ phân cấp liệu

 Kết hợp liệu hành vi

Sơ đồ phân cấp lớp Sơ đồ phân cấp liệu

(14)

Đối tượng lớp Đối tượng lớp

 Ta định nghĩa đối tượng "cái đó" có ý

nghĩa cho vấn đề ta quan tâm Đối tượng phục vụ hai mục đích: Giúp hiểu rõ giới thực cung cấp sở cho việc cài đặt máy

 Mỗi đối tượng có nét nhận dạng để phân biệt

(15)

Đối tượng lớp Đối tượng lớp

 Các đối tượng có đặc tính tương tự gom

chung lại thành lớp đối tượng Ví dụ Người lớp đối tượng Một lớp đối tượng đặc trưng thuộc tính, hoạt động (hành vi)

 Một thuộc tính (attribute) giá trị liệu cho

đối tượng lớp Tên, Tuổi, Cân nặng thuộc tính Người

tính Người

 Một thao tác (operation) hàm hay phép bieán

(16)

Sơ đồ đối tượng Sơ đồ đối tượng

 Ta dùng sơ đồ đối tượng để mô tả lớp đối tượng Sơ

đồ đối tượng bao gồm sơ đồ lớp sơ đồ thể

 Sơ đồ lớp mô tả lớp đối tượng hệ thống,

lớp đối tượng diễn tả hình chữ nhật có phần: phần đầu tên lớp, phần thứ hai mơ tả

thuộc tính phần thứ ba mô tả thao tác đối tượng lớp

(17)

Sơ đồ lớp sơ đồ thể hiện Sơ đồ lớp sơ đồ thể hiện

Sinh viên Họ tên

Năm sinh Mã số

Điểm TB

(Sinh viên) Nguyễn Vaên A 1984

0610234T 9.2

Tên lớp

Thuộc tính

Điểm TB Đi học Đi thi

Phân loại

9.2

(18)

Đối tượng lớp Đối tượng lớp

 Cùng thao tác áp dụng cho nhiều lớp

đối tượng khác nhau, thao tác gọi có tính đa dạng (polymorphism)

 Mỗi thao tác lớp đối tượng cụ thể tương ứng với

một cài đặt cụ thể khác Một cài đặt gọi phương thức (method)

 Một đối tượng cụ thể thuộc lớp gọi thể

hiện (instance) lớp Joe Smith, 25 tuổi, nặng

 Một đối tượng cụ thể thuộc lớp gọi thể

(19)

Cài đặt lớp C++ Cài đặt lớp C++

 Lớp C++ cài đặt kiểu liệu trừu tượng

người sử dụng định nghĩa, cho phép kết hợp liệu, phép toán, hàm liên quan để tạo đơn vị

chương trình Các lớp có đầy đủ ưu điểm tiện lợi kiểu liệu nội Lớp tách rời phần

giao diện (chỉ liên quan với người sử dụng) phần cài đặt lớp

đặt lớp

 Lớp C++ cài đặt sử dụng từ khoá struct

(20)

Ví dụ so sánh: Xây dựng kiểu liệu stack. Ví dụ so sánh: Xây dựng kiểu liệu stack.

1 Cách tiếp cận cổ điển: // Stack1.cpp :

//Dung cau truc va ham toan cuc

#include <iostream.h> typedef int bool;

typedef int Item;

const bool false = 0, true = 1; const bool false = 0, true = 1; struct Stack

{

Item *st, *top; int size;

(21)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

void StackInit(Stack *ps, int sz) {

ps->st = ps->top = new Item[ps->size=sz]; }

void StackCleanUp(Stack *ps) {

delete [] ps->st; delete [] ps->st; }

bool StackFull(Stack *ps) {

(22)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

bool StackEmpty(Stack *ps) {

return (ps->top <= ps->st); }

bool StackPush(Stack *ps, Item x) {

{

if (StackFull(ps)) return false; *ps->top++ = x;

(23)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

bool StackPop(Stack *ps, Item *px) {

if (StackEmpty(ps)) return false; *px = * ps->top;

(24)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

void XuatHe16(long n) {

static char hTab[] = “0123456789ABCDEF”; Stack s;

StackInit(&s,8); int x;

do {

StackPush(&s, n%16); StackPush(&s, n%16); n /= 16;

} while(n);

while(StackPop(&s,&x)) cout << hTab[x];

(25)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

Nhận xét:

 Giải vấn đề

 Khai báo cấu trúc liệu nằm riêng, hàm xử lý

liệu nằm riêng nơi khác Do khó theo dõi quản lý hệ thống lớn Vì khó bảo trì

 Mọi thao tác có tham số trỏ đến đối

tượng cần thao tác Tư tưởng thể hàm hay

 Mọi thao tác có tham số trỏ đến đối

tượng cần thao tác Tư tưởng thể hàm hay thủ tục đóng vai trị trọng tâm Đối tượng gởi đến cho hàm xử lý

 Trình tự sử dụng qua bước: Khởi động, sử dụng thực

(26)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

2 Cách tiếp cận dùng hàm thành phần:

//

struct Stack {

Item *st, *top; int size;

void Init(int sz) {st = top = new Item[size=sz];}

Item[size=sz];}

void CleanUp() {if (st) delete [] st;} bool Full() const {return (top - st >= size);}

bool Empty() const {return (top <= st);} bool Push(Item x);

(27)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

bool Stack::Push(Item x) {

if (Full()) return false; *top++ = x;

return true; }

bool Stack::Pop(Item *px) {

if (Empty()) return false; *px = * top;

(28)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

void XuatHe16(long n) {

static char hTab[] = “0123456789ABCDEF”; Stack s;

s.Init(8); int x;

do {

s.Push(n%16); n /= 16;

} while(n);

while(s.Pop(&x)) cout << hTab[x]; s.CleanUp();

(29)

Ví dụ so sánh (tt) Ví dụ so sánh (tt)

Nhận xét:

 Giải vấn đề

 Dữ liệu hàm xử lý liệu gom vào chỗ

bên cấu trúc Do dễ theo dõi quản lý, dễ bảo trì nâng cấp

 Các thao tác bớt tham số so với cách tiếp cận

cổ điển Vì việc lập trình gọn Tư tưởng thể cổ điển Vì việc lập trình gọn Tư tưởng thể đối tượng đóng vai trị trọng tâm Đối tượng

thực thao tác

 Trình tự sử dụng qua bước: Khởi động, sử dụng thực

(30)

Các hàm thành phần. Các hàm thành phần.

 Là hàm khai báo lớp Hàm thành phần

được định nghĩa bên bên lớp

 Hàm thành phần có nghi thức giao tiếp giống với

hàm bình thường khác: có tên, danh sách tham số, giá trị trả

 Gọi hàm thành phần phép toán dấu chấm (.)

dấu mũi tên (->) dấu mũi tên (->)

Stack s, *ps = &s; s.Init(10);

(31)

Lớp Lớp

 Trong cách tiếp cận dùng struct hàm thành phần,

người sử dụng có toàn quyên truy xuất, thay đổi

thành phần liệu đối tượng thuộc cấu trúc Ví dụ:

Stack s;

s.Init(10);

s.size = 100; // Nguy hiem for (int i = 0; i < 20; i++) for (int i = 0; i < 20; i++)

s.Push(i);

 Vì vậy, ta khơng có an toàn liệu Lớp

phương tiện để khắc phục nhược điểm

 Lớp có cách thay từ khoá struct từ khoá

(32)

Lớp Lớp

 Trong lớp thành phần riêng tư

(private) nghĩa giới bên ngồi khơng phép truy xuất Do có an tồn liệu

class Stack {

Item *st, *top; int size;

int size;

void Init(int sz) {st = top = new Item[size=sz];}

void CleanUp() {if (st) delete [] st;}

bool Full() const {return (top - st >= size);} bool Empty() const {return (top <= st);}

(33)

Lớp Lớp

 Phát biểu:

s.size = 100; // Bao sai

(34)

Thuoäc tính truy xuất Thuộc tính truy xuất

 Tuy nhiên lớp trở thành vô dụng hàm

thành phần trở thành private khơng dùng Điều khắc phục nhờ thuộc tính truy xuất

 Thuộc tính truy xuất thành phần lớp rõ

phần chương trình phép truy xuất đến

(35)

Thuộc tính truy xuất Thuộc tính truy xuaát

 Các thành phần nội lớp, bao gồm liệu

các hàm phục vụ nội đặt phần private Các hàm nhằm mục đích cho người sử dụng dùng đặt phần public

(36)

// Stack.h class Stack {

Item *st, *top; int size;

void Init(int sz) {st = top = new Item[size=sz];} void CleanUp() {delete [] st;}

public:

Stack(int sz = 20) {Init(sz);} Stack(int sz = 20) {Init(sz);} ~Stack() {delete [] st;}

bool Full() const {return (top - st >= size);}

bool Empty() const {return (top <= st);} bool Push(Item x);

(37)

Ví dụ lớp thuộc tính truy xuất Ví dụ lớp thuộc tính truy xuất

// Stack.cpp

#include "stack.h"

bool Stack::Push(Item x) {

if (Full()) return false; *top++ = x;

return true; }

}

bool Stack::Pop(Item *px) {

(38)

Ví dụ lớp thuộc tính truy xuất Ví dụ lớp thuộc tính truy xuất

// he16.cpp

#include "stack.h"

void XuatHe16(long n) {

static char hTab[] = “0123456789ABCDEF”; Stack s(8); int x;

do { {

s.Push(n%16); n /= 16;

} while(n);

while(s.Pop(&x))

(39)

Sử dụng phạm vi truy xuất Sử dụng phạm vi truy xuất

 Phạm vi truy xuất sử dụng cho phép ta kết

luận: Nhìn vào lớp thấy thao tác lớp

 Người dùng bình thường khai thác hết chức

năng (public) lớp

 Người dùng cao cấp thay đổi chi tiết cài đặt, cải

(40)

Tự tham chiếu Tự tham chiếu

 Là tham số ngầm định hàm thành phần trỏ đến đối

tượng Nhờ hàm thành phần biết thao tác đối tượng

 Khi đối tượng gọi thao tác, địa đối tượng

được gởi cách ngầm định với tên this, tên thành phần đối tượng hiểu đối tượng có địa this

địa this naøy

bool Stack::Push(Item x) {

if (Full()) // if (this->Full()) return false;

*top++ = x; // this->top++ = x; return true;

(41)

Phương thức thiết lập hủy bỏ Phương thức thiết lập hủy bỏ

 Phương thức thiết lập huỷ bỏ xây dựng nhằm

mục đích khắc phục lỗi quên khởi động đối tượng khởi động dư Việc quên khởi động đối tượng thường gây lỗi khó tìm

 Phương thức thiết lập hàm thành phần đặc biệt

tự động gọi đến đối tượng thuộc lớp tạo Người ta thường lợi dụng đặc tính để khởi tạo Người ta thường lợi dụng đặc tính để khởi động đối tượng

 Phương thức thiết lập có tên trùng với tên lớp để phân

(42)

Phương thức thiết lập hủy bỏ Phương thức thiết lập hủy bỏ

 Có thể có nhiều phiên khác phương thức

thiết lập

 Phương thức huỷ bỏ hàm thành phần đặc biệt tự

động gọi đến đối tượng bị huỷ Người ta thường lợi dụng đặc tính để dọn dẹp đối tượng

 Phương thức huỷ bỏ bắt đầu dấu ngã (~) theo sau

bởi tên lớp để phân biệt với hàm thành phần tên lớp để phân biệt với hàm thành phần khác

(43)

Phương thức thiết lập hủy bỏ Phương thức thiết lập hủy bỏ

typedef int Item; class Stack

{

Item *st, *top; int size;

void Init(int sz);

void CleanUp() {delete [] st;} public:

Stack(int sz = 20) {Init(sz);} Stack(int sz = 20) {Init(sz);} ~Stack() {CleanUp();}

bool Full() const {return (top - st >= size);}

bool Empty() const {return (top <= st);} bool Push(Item x);

(44)

Hàm bạn (friends) Hàm bạn (friends)

 Nguyên tắc chung thao tác lớp thơng qua

hàm thành phần Tuy nhiên có trường hợp ngoại lệ, hàm phải thao tác hai lớp

 Hàm bạn lớp hàm khai báo bên

ngoài phép truy xuất thành phần riêng tư lớp

 Ta làm hàm trở thành hàm bạn lớp cách  Ta làm hàm trở thành hàm bạn lớp cách

đưa khai báo hàm vào lớp, thêm từ khoá friend đầu

 Ta dùng hàm bạn trường hợp hàm phải hàm

(45)

Hàm thành phần hằng Hàm thành phần hằng

 Hàm thành phần hàm thành phần áp

dụng cho đối tượng

 Ta qui định hàm thành phần cách

thêm từ khố const vào cuối khai báo

 Ta khai báo hàm thành phần không thay

(46)

Hàm thành phần hằng Hàm thành phần hằng

inline char *strdup(const char *s) {

return strcpy(new char[strlen(s) + 1], s); }

class string {

char *p; public:

string(char *s = "") {p = strdup(s);} ~string() {delete [] p;}

string(const string &s2) {p = strdup(s2.p);} void Output() const {cout << p;}

(47)

Hàm thành phần hằng Hàm thành phần hằng

void main() {

const string Truong("DH BC TDT"); string s("ABCdef");

s.Output(); s.ToLower(); s.Output(); s.Output();

Truong.Output();

(48)

Thành phần tónh (static members) Thành phần tónh (static members)

 Thành phần liệu tĩnh thành phần liệu dùng

chung cho đối tượng thuộc lớp

 Hàm thành phần tĩnh hàm thành phần hoạt

động khơng cần liệu đối tượng, nói cách khác, khơng cần đối tượng

 Ta dùng hàm thành phần tĩnh thay hàm tồn cục

nó có liên quan mật thiết với lớp có liên quan mật thiết với lớp

 Ta dùng hàm thành phần tĩnh để tạo đối tượng có

(49)

Ví dụ thành phần tónh: CDate Ví dụ thành phần tónh: CDate typedef int bool;

const bool false = 0, true = 1; class CDate

{

static int dayTab[][13]; int day, month, year;

public: public:

static bool LeapYear(int y) {return y%400 == || y%4==0 && y%100 != 0;}

static int DayOfMonth(int m, int y);

(50)

Ví dụ thành phần tónh : CDate Ví dụ thành phần tónh : CDate int CDate::dayTab[][13] =

{

{0,31,28,31,30,31,30,31,31,30,31,30,31}, {0,31,29,31,30,31,30,31,31,30,31,30,31} };

int CDate::DayOfMonth(int m, int y) {

return dayTab[LeapYear(y)][m]; return dayTab[LeapYear(y)][m]; }

bool betw(int x, int a, int b) {

(51)

Ví dụ thành phần tónh : CDate Ví dụ thành phần tónh : CDate bool CDate::ValidDate(int d, int m, int y) {

return betw(m,1,12) &&

betw(d,1,DayOfMonth(m,y)); }

void CDate::Input() {

int d,m,y; int d,m,y;

cin >> d >> m >> y;

while (!ValidDate(d,m,y)) {

cout << "Please enter a valid date: "; cin >> d >> m >> y;

(52)

2.3 Thiết lập huỷ bỏ đối tượng 2.3 Thiết lập huỷ bỏ đối tượng Ta cần kiểm soát phương thức thiết lập gọi, phương thức huỷ bỏ gọi

• Khi đối tượng thiết lập gọi? Khi đối tượng

được tạo

• Khi phương thức huỷ bỏ gọi? Khi đối tượng bị

huỷ

Thời gian từ đối tượng tạo đến bị huỷ

• Thời gian từ đối tượng tạo đến bị huỷ

đi gọi thời gian sống

 Vậy vấn đề xác định phương thức thiết lập

huỷ bỏ gọi trở thành:

(53)

Thiết lập huỷ bỏ đối tượng Thiết lập huỷ bỏ đối tượng

 Thời gian sống đối tượng khác tuỳ thuộc đối

tượng thuộc lớp lưu trữ (storage class) Trong C++ có lớp lưu trữ sau:

auto global static

free stored free stored

 Ta xét loại sau: Đối tượng tự động

Đối tượng toàn cục Đối tượng tĩnh

(54)

Đối tượng tự động Đối tượng tự động

 Đối tượng tự động (automatic objects) đối tượng

tự động sinh tự động bị huỷ

 Đối tượng địa phương

• Là biến khai báo, định nghĩa bên khối

• Nó tự động sinh chương trình thực ngang dịng

lệnh chứa định nghĩa bị huỷ sau chương trình hồn tất khối chứa định nghĩa

khối chứa định nghĩa

 Khi khởi động đối tượng đối tượng

kiểu, chế tạo đối tượng chép bit, đối tượng khởi động chia sẻ tài

(55)

Đối tượng biến địa phương Đối tượng biến địa phương #include <iostream.h>

#include <string.h>

char *strdup(const char *s) {

return strcpy(new char[strlen(s) + 1], s); }

class string class string {

char *p; public:

string(char *s = "") {p = strdup(s);}

(56)

void main() {

string a("Nguyen Van A");

string b = a; // String b(a) a.Output(); cout << "\n";

(57)

 Xuất liệu thực đoạn chương trình trên:

Nguyen Van A Nguyen Van A delete 0x0f06 delete 0x0f06

 Đối tượng b có nội dung vật lý giống với a, nghĩa dùng

(58)

Đối tượng tham số truyền giá trị Đối tượng tham số truyền giá trị

 Đối tượng tham số hàm, truyền giá trị tham

số hình thức tham số thực sự, nên có nội dung vật lý giống tham số thực chế chép bit

extern char *strdup(const char *s); class String

{

char *p; char *p; public:

String(char *s = "") {p = strdup(s);}

~String() {cout << "delete "<< (void *)p << "\n"; delete [] p;}

(59)

Đối tượng tham số truyền giá trị Đối tượng tham số truyền giá trị

bool String::Compare(String s) const {

return strcmp(p,s.p); }

void main() {

String a("Nguyen Van A"); String b("Le Van Beo"); int c = a.Compare(b);

(60)

Đối tượng tham số truyền giá trị Đối tượng tham số truyền giá trị

 Khi thực đoạn chương trình trên, ta xuất liệu

(có thể thay đổi lần thực khác máy khác):

delete 0x0f34 a > b

(61)

Đối tượng giá trị trả về Đối tượng giá trị trả về

extern char *strdup(const char *s); class String

{

char *p; public:

String(char *s = "") {p = strdup(s);}

~String() {cout << "delete "<< (void *)p << "\n"; delete [] p;}

delete [] p;}

void Output() const {cout << p;} bool Compare(String s) const;

(62)

Đối tượng giá trị trả về Đối tượng giá trị trả về

String String::UpCase() const {

String r = *this; strupr(r.p);

return r; }

void main() {

{

clrscr();

String a("Nguyen Van A");

cout << "a = "; a.Output(); cout << "\n"; String A;

A = a.UpCase();

(63)

Đối tượng giá trị trả về Đối tượng giá trị trả về

 Khi thực đoạn chương trình trên, ta xuât liệu

a = Nguyen Van A delete 0x0f36 delete 0x0f36 a = 2Ô2ÔEN VAN A A = 2Ô2ÔEN VAN A delete 0x0f36 delete 0x0f36

Null pointer assignment

(64)

Đối tượng giá trị trả về Đối tượng giá trị trả về

Các lỗi sai gây đoạn chương trình chép đối tượng (phát biểu String r = *this), đối tượng giá trị trả phép gán (A = a.Upcase)

 Ta khắc phục lỗi gây phép gán cách

thay hai phát biểu khai báo A gán phát biểu khởi động:

(65)

Đối tượng giá trị trả về Đối tượng giá trị trả về

void main() {

clrscr();

String a("Nguyen Van A");

cout << "a = "; a.Output(); cout << "\n"; String A = a.UpCase();

cout << "a = "; a.Output(); cout << "\n"; cout << "A = "; a.Output(); cout << "\n"; }

(66)

Đối tượng giá trị trả về Đối tượng giá trị trả về

 Xuất liệu trường hợp a = Nguyen Van A

delete 0x0d32

a = NGUYEN VAN A A = NGUYEN VAN A delete 0x0d32

delete 0x0d32 delete 0x0d32

(67)

Phương thức thiết lập chép Phương thức thiết lập chép

 Các lỗi sai nêu gây chép đối tượng, ta có

thể khắc phục cách “dạy” trình biên dịch chép đối tượng cách luận lý thay chép bit theo nghĩa vật lý Điều thực nhờ

phương thức thiết lập chép

 Phương thức thiết lập chép phương thức thiết lập

(68)

Phương thức thiết lập chép Phương thức thiết lập chép

 Phương thức thiết lập chép thực chép theo

nghĩa logic, thông thường tạo nên tài nguyên (sao chép sâu)

 Phương thức thiết lập chép chia sẻ tài

nguyên cho đối tượng (sao chép nông) Trong trường hợp này, cần có chế để kiểm sốt sử huỷ bỏ đối

(69)

Phương thức thiết lập chép Phương thức thiết lập chép extern char *strdup(const char *s);

class String {

char *p; public:

String(char *s = "") {p = strdup(s);} String(const String &s) {p =

strdup(s.p);} strdup(s.p);}

~String() {cout << "delete "<< (void *)p << "\n"; delete [] p;}

void Output() const {cout << p;} bool Compare(String s) const;

(70)

Phương thức thiết lập chép Phương thức thiết lập chép

bool String::Compare(String s) const {

return strcmp(p,s.p); }

String String::UpCase() const {

String r = *this; String r = *this; strupr(r.p);

(71)

Phương thức thiết lập chép Phương thức thiết lập chép void main()

{

clrscr();

String a("Nguyen Van A"); String b("Le Van Beo"); String aa = a;

int c = a.Compare(b);

cout << (c > ? "a > b" : c == ? "a = b" : "a < b") << "\n";

cout << "a = "; a.Output(); cout << "\n"; String A = a.UpCase();

(72)

Phương thức thiết lập chép Phương thức thiết lập chép

 Xuất liệu trường hợp sau: delete 0x0d84

a > b

a = Nguyen Van A delete 0x0d84

a = Nguyen Van A A = NGUYEN VAN A A = NGUYEN VAN A delete 0x0d96

delete 0x0d72 delete 0x0d62 delete 0x0d50

 Mỗi đối tượng có tài nguyên riêng nên không xảy

(73)

Phương thức thiết lập chép Phương thức thiết lập chép

 Tham số phương thức thiết lập chép bắt buộc

tham chieáu

 Phương thức thiết lập chép dùng để

chép nông, tài nguyên chia sẻ có biến đếm để kiểm sốt

Lưu ý:

Nếu đối tượng khơng có tài ngun riêng khơng cần

 Nếu đối tượng khơng có tài ngun riêng khơng cần

phương thức thiết lập chép

 Khi truyền tham số đối tượng thuộc lớp có phương

(74)

Sao chép nông chép sâu Sao chép nông chép sâu

 Dùng phương thức thiết lập chép trên,

đối tượng có tài nguyên riêng chép sâu

 Ta chép nông cách chia sẻ tài nguyên

và dùng biến đếm để kiểm soát số thể đối tượng có chia sẻ tài nguyên

 Khi đối tượng thay đổi nội dung, phải tách

(75)

Ví dụ chép nông Ví dụ chép nông extern char *strdup(const char *s);

class StringRep {

friend class String; char *p;

int n;

StringRep(const char *s) {p = strdup(s); n = 1;} ~StringRep() {cout << "delete ” << (void *)p << ~StringRep() {cout << "delete ” << (void *)p <<

(76)

Ví dụ chép nông Ví dụ chép nông

class String {

StringRep *rep; public:

String(const char *s = "") {rep = new StringRep(s);}

String(const String &s) {rep = s.rep; rep->n++;}

rep->n++;} ~String();

void Output() const {cout << rep->p;} bool Compare(String s) const;

String UpCase() const; void ToUpper();

(77)

Ví dụ chép nông Ví dụ chép nông

String::~String() {

if ( rep->n <= 0) delete rep;

}

bool String::Compare(String s) const {

return strcmp(rep->p,s.rep->p); return strcmp(rep->p,s.rep->p); }

String String::UpCase() const {

(78)

Ví dụ chép nông Ví dụ chép nông void main()

{

clrscr();

String a("Nguyen Van A"); String b("Le Van Beo"); String aa = a;

int c = a.Compare(b);

cout << (c > ? "a > b" : c == ? "a = b" : "a cout << (c > ? "a > b" : c == ? "a = b" : "a < b") << "\n";

cout << "a = "; a.Output(); cout << "\n"; String A = a.UpCase();

(79)

Ví dụ chép nông Ví dụ chép nông

 Xuất liệu thực đoạn chương trình sau: a > b

a = Nguyen Van A a = Nguyen Van A A = NGUYEN VAN A delete 0x0d8a

(80)

Ví dụ chép nông Ví dụ chép nông

delete 0x0d84 a > b

a = Nguyen Van A delete 0x0d84

a > b

a = Nguyen Van A a = Nguyen Van A A = NGUYEN VAN A

So sánh với chép sâu: Bên trái, dùng chép sâu, bên phải dùng chép nông

delete 0x0d84

a = Nguyen Van A A = NGUYEN VAN A delete 0x0d96

delete 0x0d72 delete 0x0d62 delete 0x0d50

A = NGUYEN VAN A delete 0x0d8a

(81)

Đối tượng tĩnh Đối tượng tĩnh

 Đối tượng tĩnh đối tượng định nghĩa tồn

cục, định nghĩa có thêm từ khố static (toàn cục địa phương)

 Đối tượng toàn cục tĩnh toàn cục tạo

bắt đầu chương trình bị huỷ kết thúc chương trình

 Đối tượng tĩnh địa phương tạo chương trình  Đối tượng tĩnh địa phương tạo chương trình

(82)

Đối tượng tĩnh Đối tượng tĩnh

 Trình tự thực chương trình gồm:

• Gọi phương thức thiết lập cho đối tượng toàn cục • Thực hàm main()

• Gọi phương thức huỷ bỏ cho đối tượng toàn cục

(83)

Ví dụ đối tượng tồn cục Ví dụ đối tượng tồn cục

 Xét đoạn chương trình sau: #include <iostream.h> void main()

{

cout << "Hello, world.\n"; }

Hãy sửa lại đoạn chương trình để có xuất liệu: Hãy sửa lại đoạn chương trình để có xuất liệu:

Entering a C++ program saying Hello, world

And then exitting…

(84)

Ví dụ đối tượng tồn cục Ví dụ đối tượng tồn cục

 Đoạn chương trình sửa lại sau: #include <iostream.h>

void main() {

cout << "Hello, world.\n"; }

class Dummy class Dummy {

public:

Dummy() {cout << "Entering a C++ program saying \n";}

~Dummy() {cout << "And then exitting ";} };

(85)

Đối tượng thành phần lớp Đối tượng thành phần lớp

 Đối tượng thành phần đối tượng khác,

một đối tượng thuộc lớp “lớn” tạo ra, thành phần tạo Phương thức thiết lập (nếu có) tự động gọi cho đối tượng thành phần

 Nếu đối tượng thành phần phải cung cấp tham số

(86)

Đối tượng thành phần lớp Đối tượng thành phần lớp

 Cú pháp để khởi động đối tượng thành phần dùng

dấu hai chấm (:) theo sau tên thành phần tham số khởi động

 Khi đối tượng kết hợp bị huỷ đối tượng thành

(87)

Đối tượng thành phần lớp Đối tượng thành phần lớp

class Diem {

double x,y; public:

Diem(double xx, double yy) {x = xx; y = yy;} //

};

class TamGiac {

{

Diem A,B,C; public:

void Ve() const; //

};

(88)

Đối tượng thành phần lớp Đối tượng thành phần lớp

class String {

char *p; public:

String(char *s) {p = strdup(s);}

String(const String &s) {p = strdup(s.p);}

~String() {cout << "delete "<< (void *)p << "\n"; delete [] p;

// };

};

class SinhVien {

String MaSo; String HoTen; int NamSinh; public:

};

(89)

Đối tượng thành phần - thiết lập Đối tượng thành phần - thiết lập class Diem

{

double x,y; public:

Diem(double xx, double yy {x = xx; y = yy;} //

(90)

Khởi động đối tượng thành phần Khởi động đối tượng thành phần

class TamGiac {

Diem A,B,C; public:

TamGiac(double xA, double yA, double xB, double yB, double xC, double yC):A(xA,yA),

B(xB,yB),C(xC,yC){} void Ve() const;

void Ve() const; //

};

(91)

Đối tượng thành phần lớp Đối tượng thành phần lớp class String

{

char *p; public:

String(char *s) {p = strdup(s);}

String(const String &s) {p = strdup(s.p);} ~String() {cout << "delete "<< (void *)p <<

"\n"; delete [] p; "\n"; delete [] p; //

(92)

Khởi động đối tượng thành phần Khởi động đối tượng thành phần class SinhVien

{

String MaSo; String HoTen; int NamSinh; public:

SinhVien(char *ht, char *ms, int ns):HoTen(ht), MaSo(ms){NamSinh = ns;}

MaSo(ms){NamSinh = ns;} //

};

(93)

Khởi động đối tượng thành phần Khởi động đối tượng thành phần

 Cú pháp dùng dấu hai chấm dùng cho đối

tượng thành phần thuộc kiểu class Diem

{

double x,y; public:

Diem(double xx, double yy):x(xx), y(yy){} //

}; };

class SinhVien {

String MaSo, HoTen; int NamSinh;

public:

(94)

Đối tượng thành phần - Huỷ bỏ Đối tượng thành phần - Huỷ bỏ

 Khi đối tượng kết hợp bị huỷ bỏ, đối tượng thành phần

của bị huỷ bỏ class SinhVien

{

String MaSo, HoTen; int NamSinh;

int SoMon; double *Diem; public:

public:

SinhVien(char *ht, char *ms, int ns, int sm, double *d); ~SinhVien() {delete [] Diem;}

// };

SinhVien::SinhVien(char *ht, char *ms, int ns, int sm, double *d):HoTen(ht), MaSo(ms), NamSinh(ns), SoMon(sm) {

(95)

Đối tượng thành phần mảng Đối tượng thành phần mảng

 Khi mảng tạo ra, phần tử

được tạo ra, phương thức thiết lập gọi cho phần tử

 Vì khơng thể cung cấp tham số khởi động cho tất

phần tử mảng nên khai báo mảng, đối

tượng mảng phải có khả tự khởi động, nghĩa thiết lập khơng cần tham số

là thiết lập không cần tham số

 Đối tượng có khả tự khởi động trường

hợp sau:

• Lớp khơng có phương thức thiết lập

(96)

Đối tượng thành phần mảng Đối tượng thành phần mảng

class Diem {

double x,y; public:

Diem(double xx, double yy):x(xx), y(yy) {}

void Set(double xx, double yy) {x = xx, y = yy;} //

};

class String class String {

char *p; public:

String(char *s) {p = strdup(s);}

String(const String &s) {p = strdup(s.p);} ~String() {cout << "delete "<< (void *)p <<

(97)

Đối tượng thành phần mảng Đối tượng thành phần mảng

class SinhVien {

String MaSo; String HoTen; int NamSinh; public:

SinhVien(char *ht, char *ms, int ns):HoTen(ht), MaSo(ms), NamSinh(ns){}

MaSo(ms), NamSinh(ns){} //

};

String as[3]; // Bao sai

Diem ad[5]; // Bao sai

(98)

Phương thức thiết lập với tham số có giá trị mặc nhiên

Phương thức thiết lập với tham số có giá trị mặc nhiên

class Diem {

double x,y; public:

Diem(double xx = 0, double yy = 0):x(xx), y(yy){}

void Set(double xx, double yy) {x = xx, y = yy;} //

// };

class String {

char *p; public:

String(char *s = “”) {p = strdup(s);}

(99)

Dùng phương thức thiết lập với tham số có giá trị mặc nhiên

Dùng phương thức thiết lập với tham số có giá trị mặc nhiên

class SinhVien {

String MaSo; String HoTen; int NamSinh; public:

SinhVien(char *ht = “Nguyen Van A”, char *ms = “19920014”, int ns =

“19920014”, int ns =

1982):HoTen(ht), MaSo(ms), NamSinh(ns){}

// };

(100)

Dùng phương thức thiết lập không tham số Dùng phương thức thiết lập không tham số

class Diem {

double x,y; public:

Diem(double xx, double yy):x(xx), y(yy){} Diem():x(0), y(0){}

// };

};

class String {

char *p; public:

String(char *s) {p = strdup(s);} String() {p = strdup(“”);}

(101)

Dùng phương thức thiết lập không tham số

Dùng phương thức thiết lập không tham số

class SinhVien {

String MaSo; String HoTen; int NamSinh; public:

SinhVien(char *ht, char *ms, int SinhVien(char *ht, char *ms, int

ns):HoTen(ht), MaSo(ms), NamSinh(ns){}

SinhVien():HoTen(“Nguyen Van A”),

MaSo(“19920014”), NamSinh(1982){} //

(102)

Đối tượng cấp phát động Đối tượng cấp phát động

 Đối tượng cấp phát động đối tượng tạo

ra phép toán new bị huỷ phép toán delete

 Phép toán new cấp đối tượng vùng heap (hay vùng

free store) gọi phương thức thiết lập cho đối tượng cấp

 Dùng new cấp đối tượng dùng delete để  Dùng new cấp đối tượng dùng delete để

huỷ đối tượng

 Dùng new delete cấp nhiều đối tượng

(103)

Đối tượng cấp phát động Đối tượng cấp phát động

class String {

char *p; public:

String(char *s) {p = strdup(s);}

String(const String &s) {p = strdup(s.p);} ~String() {delete [] p;}

// };

};

class Diem {

double x,y; public:

(104)

Cấp huỷ đối tượng Cấp huỷ đối tượng

int *pi = new int;

int *pj = new int(15);

Diem *pd = new Diem(20,40);

String *pa = new String("Nguyen Van A"); //

(105)

Cấp huỷ nhiều đối tượng Cấp huỷ nhiều đối tượng

 Trong trường hợp cấp nhiều đối tượng, ta cung

cấp tham số cho phần tử cấp:

int *pai = new int[10];

Diem *pad = new Diem[5]; // Bao sai String *pas = new String[5]; // Bao sai //

 Thông báo lỗi cho đoạn chương trình sau:  Thơng báo lỗi cho đoạn chương trình sau:

Cannot find default constructor to initialize array element of type 'Diem'

Cannot find default constructor to initialize array element of type String’

(106)

Cấp huỷ nhiều đối tượng Cấp huỷ nhiều đối tượng

class String {

char *p; public:

String(char *s = "Alibaba") {p = strdup(s);} String(const String &s) {p = strdup(s.p);} ~String() {delete [] p;}

// };

class Diem {

double x,y; public:

Diem(double xx, double yy):x(xx),y(yy){}; Diem():x(0),y(0){};

(107)

Cấp huỷ nhiều đối tượng Cấp huỷ nhiều đối tượng

 Khi phần tử cấp khởi động với

cùng giá trị

int *pai = new int[10]; Diem *pad = new Diem[5];

// ca diem co cung toa (0,0) String *pas = new String[5];

// Ca chuoi cung duoc khoi dong bang “Alibaba”

Việc huỷ nhiều đối tượng thực cách dùng

// Ca chuoi cung duoc khoi dong bang “Alibaba”  Việc huỷ nhiều đối tượng thực cách dùng

delete có thêm dấu [] trước

(108)

2.4 Giao diện chi tiết cài đặt 2.4 Giao diện chi tiết cài đặt

 Lớp có hai phần tách rời, phần giao diện khai báo

trong phần public để người sử dụng “thấy” sử dụng, hai chi tiết cài đặt bao gồm liệu khai báo

phần private lớp chi tiết mã hoá hàm thành phần, vơ hình người dùng

 Ta thay đổi uyển chuyển chi tiết cài đặt, nghĩa

có thể thay đổi tổ chức liệu lớp, có thể thay đổi tổ chức liệu lớp, thay đổi chi tiết thực hàm thành phần (do thay đổi tổ chức liệu để cải tiến giải thuật) Nhưng bảo đảm không thay đổi phần giao diện khơng ảnh hưởng đến người sử dụng, khơng làm đổ vỡ kiến trúc hệ thống

 Lớp ThoiDiem cài đặt với thành phần

(109)

Lớp ThoiDiem – Cách 1 Lớp ThoiDiem – Cách 1

class ThoiDiem {

int gio, phut, giay;

static bool HopLe(int g, int p, int gy); public:

ThoiDiem(int g = 0, int p = 0, int gy = 0) {Set(g,p,gy);}

(110)

Lớp ThoiDiem – Cách 2 Lớp ThoiDiem – Cách 2

class ThoiDiem {

long tsgiay;

static bool HopLe(int g, int p, int gy); public:

ThoiDiem(int g = 0, int p = 0, int gy = 0) {Set(g,p,gy);}

void Set(int g, int p, int gy); void Set(int g, int p, int gy);

int LayGio() const {return tsgiay / 3600;}

int LayPhut() const {return (tsgiay%3600)/60;} int LayGiay() const {return tsgiay % 60;}

void Nhap();

(111)

Giao diện chi tiết cài đặt Giao diện chi tiết cài đặt

 Có thể xem chi tiết đầy đủ lớp thời điểm cài đặt

giờ, phút, giây cài đặt tổng số giây tập tin nguồn thgian.cpp thgian2.cpp,

 Tương tự lớp Stack cài đặt dạng mảng

(112)

2.5 Các nguyên tắc xây dựng lớp 2.5 Các nguyên tắc xây dựng lớp

 Khi ta nghĩ đến “nó” khái niệm riêng rẽ,

xây dựng lớp biểu diễn khái niệm Ví dụ lớp SinhVien

 Khi ta nghĩ đến “nó” thực thể riêng rẽ, tạo đối

tượng thuộc lớp Ví dụ đối tượng Sinh viên “Nguyen Van A” (và thuộc tính khác mã số, năm sinh…)

 Lớp biểu diễn cụ thể khái niệm, lớp  Lớp biểu diễn cụ thể khái niệm, lớp

ln ln DANH TỪ

 Các thuộc tính lớp thành phần liệu, nên

chúng luôn DANH TỪ

 Các hàm thành phần thao tác rõ hoạt động

của lớp nên hàm ĐỘNG TỪ

(113)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

// SAI class TamGiac { // DUNG class TamGiac {

 Các thuộc tính suy diễn từ thuộc tính khác dùng hàm thành phần để thực tính tốn Chu vi, diện tích tam giác thuộc tính suy diễn

{

Diem A,B,C;

(114)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

 Cá biệt có số thuộc tính suy diễn địi hỏi

nhiều tài ngun thời gian để thực tính tốn, ta khai báo liệu thành phần Ví dụ tuổi trung bình dân Việt Nam

class QuocGia {

long DanSo;

double DienTich; double DienTich;

double TuoiTrungBinh; //

public:

double TinhTuoiTB() const; //

(115)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

 Chi tiết cài đặt, bao gồm liệu phần mã hố

hàm thành phần thay đổi uyển chuyển phần giao diện, nghĩa phần khai báo hàm thành phần cần phải cố định để không ảnh hưởng đến người sử dụng (xem phần 2.4) Tuy nhiên nên cố gắng cài đặt liệu cách tự nhiên theo khái niệm

// NEN // KHONG NEN

// NEN

class PhanSo {

int tu, mau; public:

// KHONG NEN class PhanSo {

(116)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

 Dữ liệu thành phần nên kết hợp thay phân rã

// NEN

class TamGiac {

Diem A,B,C; public:

// KHONG NEN class TamGiac {

double xA, yA,

xB, yB, xC, public: // }; class HinhTron { Diem Tam; double BanKinh; public:

xB, yB, xC, yC; public: // }; class HinhTron {

(117)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

 Chi tiết cài đặt, bao gồm liệu phần mã hố

hàm thành phần thay đổi uyển chuyển phần giao diện, nghĩa phần khai báo hàm thành phần cần phải cố định để không ảnh hưởng đến người sử dụng (xem phần 2.4)

 Dữ liệu thành phần nên kết hợp thay phân rã

// NEN // KHONG NEN

// NEN

class TamGiac {

Diem A,B,C; public:

//

// KHONG NEN class TamGiac {

double xA, yA,

(118)

Các nguyên tắc xây dựng lớp Các nguyên tắc xây dựng lớp

 Trong trường hợp, cần có phương thức thiết lập để

khởi động đối tượng

 Nên có phương thức thiết lập có khả tự khởi động

không cần tham số

 Nếu đối tượng có nhu cầu cấp phát tài ngun phải

có phương thức thiết lập, phương thức thiết lập chép để khởi động đối tượng đối tượng kiểu có để khởi động đối tượng đối tượng kiểu có phương thức huỷ bỏ để dọn dẹp Ngồi cịn phải có phép gán (chương tiếp theo)

 Ngược lại, đối tượng đơn giản không cần tài nguyên

Ngày đăng: 20/04/2021, 01:35

Xem thêm:

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN

w