C++ xây dựng tính đóng bằng cách cho phép mọi thành viên của một lớp có thể được khai báo bằng các từ khoá public, private, hay protected. (xem thêm các khái niệm cơ bản trong ngôn ngữ OOP). Một thành viên private chỉ có thể được truy cập từ các phương pháp (hàm nội tại) là thành viên của chính lớp đó hay được truy cập từ các hàm và các lớp được đặc biệt cho phép sử dụng bằng cách dùng từ khóa friend. Một thành viên protected của một lớp sẽ có thể truy cập được từ các thành viên (nào đó) của các lớp có tính kế thừa của nó hay cũng có thể truy cập được từ các thành viện của chính lớp đó và của mọi thành viên friend. Nguyên lý của OOP là mọi và chỉ có các hàm là có thể truy cập được đến các giá trị nội tại của cùng lớp thì nên có tính đóng. C++ có hỗ trợ đặc tính này (qua các hàm thành viên và các hàm friend), nhưng C++ lại không là yêu cầu bắt buộc: người lập trình có thể khai báo các phần hay tất cả các giá trị nội tại là công cộng (public), và cũng cho phép làm cho toàn bộ lớp trở thành công cộng. Lí do là vì C++ hỗ trợ không chỉ lập trình hướng đối tượng mà còn hỗ trợ các mẫu hình yếu hơn như là lập trình môđun. Một thói quen tốt cần có trong thực hành là khai báo mọi dữ liệu đều là riêng tư (private), hay ít nhất ở dạng bảo tồn, và sau đó, tạo ra một giao diện nhỏ (thông qua các phương pháp) cho người dùng của lớp này dấu đi các chi tiết thiết lập bên trong.
Trang 1Lập trình hướng đối tượng
O BJECT O RIENTED P ROGRAMMING (OOP)
2 Chương I
Giới thiệu OOP
Được xem là:
Mục đích:
1 Tổng quan về các kỹ thuật lập trình
1.1 Lập trình tuyến tính 1.2 Lập trình cấu trúc 1.3 Lập trình đơn thể (Module) 1.4 Lập trình hướng đối tượng
LT Truyền thống
Trang 25
1.1 Lập trình tuyến tính
Lập trình tuyến tính:
• Còn gọi là lập trình phi cấu trúc
• Giải quyết các bài toán tương đối nhỏ, đơn giản
Không sử dụng lại được các đoạn mã
Không có khả năng kiểm soát phạm vi truy xuất dữ liệu
Mọi dữ liệu trong chương trình là toàn cục
Dữ liệu có thể bị sửa đổi ở bất cứ vị trí nào trong chương trình
phần mềm
1.2 Lập trình cấu trúc
con:
Thủ tục (Procedure)
Hàm (Function)
Độc lập với nhau và có dữ liệu riêng
Trao đổi qua: tham số và biến toàn cục
Trừu tượng hoá dữ liệu
Trừu tượng hoá thao tác
C, Pascal
Foxpro …
Trang 3 Chương trình được chia thành nhiều phần nhỏ
Các phần tương tác thông qua việc gọi đơn thể
Mỗi module có dữ liệu của riêng nó
10
Nhược điểm của lập trình truyền thống
Chương trình khó kiểm soát
Khó khăn trong việc bổ sung, nâng cấp chương trình
Khi thay đổi, bổ sung dữ liệu dùng chung thì phải thay đổi gần như tất cả thủ tục/hàm liên quan
Khả năng sử dụng lại các đoạn mã chưa nhiều
Không mô tả đầy đủ, trung thực hệ thống trong thực tế
1.4 Lập trình hướng đối tượng
Mô tả chính xác các đối tượng trong thế giới
thực
Lấy đối tượng làm nền tảng xây dựng thuật toán
Thiết kế xoay quanh dữ liệu của hệ thống
Chương trình được chia thành các lớp đối tượng
Dữ liệu được đóng gói, che dấu và bảo vệ
Đối tượng làm việc với nhau qua thông báo
1.5 Lập trình hướng đối tượng
Program
Trang 413
2 Một số khái niệm cơ bản
2.1 Hệ thống hướng đối tượng (OOP System)
2.2 Đối tượng (Object)
2.3 Thuộc tính & Phương thức
2.4 Lớp & Lớp con (Class)
2.5 Lớp trừu tượng (Abstract Class)
2.6 Truyền thông điệp (Message)
2.7 Sự trừu tượng hoá
Gửi & nhận thông báo
2.2 Đối tượng (Object)
trong thế giới thực
Có thể là một thực thể vật lý
Có thể là một khái niệm trừu tượng
Tham số nội tại
Thuộc tính được xác định kiểu, gồm:
Trang 5 Được thiết kế nhằm tạo ra lớp có đặc tính tổng quát
Bản thân nó chưa có ý nghĩa nên chưa thể viết mã cho đối tượng
Phương thức của đối tượng đích (đối tượng chủ)
Tên Phương thức cần thực hiện
Các thông tin cần thiết khác (tham số)
thức như sau:
Gửi thông báo và tham số cho đối tượng
Kiểm tra tính hợp lệ của thông báo
Gọi thực hiện hàm tương ứng phương thức
2.7 Sự trừu tượng hoá
Là khả năng bỏ qua hay không để ý tới các thành phần không quan trọng
Các loại trừu tượng hoá:
Trừu tượng hoá dữ liệu: không quan tâm các
chi tiết không quan trọng bên trong
Trừu tượng hoá chức năng: không quan tâm làm thế nào để thực hiện công việc
Tóm lại:
Chỉ quan tâm tới đặc điểm quan trọng
Bỏ qua các chi tiết không liên quan
Trang 6 Khả năng đưa một phương thức có cùng
tên trong các lớp con
Tìm dữ liệu dùng chung, chia sẻ
Xác định lớp cơ sở dựa vào dữ liệu dùng chung
Xây dựng lớp dẫn xuất từ lớp cơ sở
Trang 725
4 Ưu điểm của OOP
Loại bỏ các đoạn mã lặp lại
Tạo ra các chương trình an toàn, bảo mật
Dễ dàng mở rộng và nâng cấp
Rút ngắn thời gian xây dựng hệ thống
Tăng năng xuất và hiệu quả hơn
Chương trình được thiết kế theo đúng qui
[quyền truy xuất:]
//khai báo các thành phần dữ liệu của lớp
[quyền truy xuất:]
//khai báo các thành phần hàm của lớp
tuân theo các qui tắc về tên
Ví dụ: SV, NGUOI, Hoa_Don, ps, Ma_Tran…
Trang 831
a Khai báo
Là khả năng truy xuất thành phần dữ liệu
Mặc định là private
private: trong phạm vi lớp đó
public: ở mọi nơi nếu đối tượng tồn tại
protected: phạm vi lớp đó và các lớp con kế thừa
a Khai báo
Khai báo thành phần
Dữ liệu:
Tương tự như khai báo biến
<kiểu dữ liệu > <tên_thành_phần>;
Chú ý: không được khởi tạo giá trị ban đầu
// <thân hàm>
}
Cách 2: định nghĩa ngay trong lớp
Trang 935
a Khai báo
Ví dụ 1:
Xây dựng cấu trúc dữ liệu mô tả sinh viên:
Dữ liệu: họ tên, ngày sinh, giới tính, Điểm toán,
Lớp các phân số
a Khai báo
Ví dụ 3:
Xây dựng cấu trúc dữ liệu mô tả các hóa đơn:
Dữ liệu: mã vật tư, tên vật tư, loại phiếu, ngày
lập, khối lượng, đơn giá, thành tiền…
Trang 10Một đối tượng thường có 4 phương thức cơ bản
Các phương thức khởi tạo: Constructor
Các phương thức truy vấn: Queries
//thân hàm }
Trang 1143
a Hàm khởi tạo (tiếp)
Như vậy hàm khởi tạo:
Có với mọi lớp
Tên hàm là tên lớp
Không có kiểu trả về không cần khai báo
Được tự động gọi khi 1 đối tượng của lớp được
tạo ra
Nếu không xây dựng thì chương trình tự động
sinh hàm khởi tạo mặc định
Trang 12Không định nghĩa lại
Trùng tên với lớp và có dấu ~ ở trước
Thực hiện một số công việc trứơc khi hệ thống
giải phóng bộ nhớ
Chương trình dịch tự động sinh hàm hủy mặc
định
48
3 Quá tải toán tử
• Khả năng cho phép 1 ký hiệu (1 phép toán) được
sử dụng với nhiều ý nghĩa, công dụng khác nhau
Quá tải toán tử +, * của lớp phân số
Quá tải toán tử + vector
Danh sách các toán tử có thể quá tải :
+ - * / = < > += -= *= /= << >>
<<= >>= == != <= >= ++ % & ^ ! |
~ &= ^= |= && || %= [] () , ->* ->
new delete new[] delete[]
Trang 13private :
int tu,mau;
public :
PhanSo operator + (PhanSo ps2);
PhanSo operator - (PhanSo ps2);
PhanSo operator * (PhanSo ps2);
PhanSo operator / (PhanSo ps2);
};
PhanSo PhanSo:: operator + (PhanSo ps2)
{ PhanSo tong;
tong.tu = this tu*ps2.mau+thismau*ps2.tu;
PhanSo ps1,ps2,tong,hieu,thuong,tich;
cin>>ps1>>ps2;
tong=ps1+ps2; // tong=ps1.operator+(ps2) hieu=ps1-ps2; // hieu=ps1.operator-(ps2) thuong=ps1/ps2; // thuong=ps1.operator/(ps2) tich=ps1*ps2; // tich=ps1.operator*(ps2) getch();
Trang 14Lập trình hướng đối tượng
O BJECT O RIENTED P ROGRAMMING (OOP)
Trang 15Làm thế nào
để thực hiện được việc truy xuất đến thành viên
friend <kiểu trả về> <tên hàm>([tham số]);
Sau đó định nghĩa hàm bạn ở ngoài lớp như các
…
friend int f(A x); //f là bạn của lớp A
… };
//Định nghĩa hàm tự do f int f(A x)
{ //truy nhập được vào các thành phần private của lớp A }
Trang 1668
Ví dụ:
Ví dụ:
Kết quả:
diem a trung voi diem b
diem a khac voi diem c
2 Hàm thành phần của 1 lớp là bạn của lớp khác
Giả sử ta có 2 lớp A và B, trong lớp B ta có hàm thành phần f được khai báo như sau:
int f(char, A)
Nếu f có nhu cầu truy xuất tới thành phần riêng của A thì f cần được khai báo là bạn của lớp A bằng câu lệnh:
friend int B:: f(char, A)
Trang 1880
Có thể cho phép nhiều đối tượng cùng chia sẽ dữ
liệu bằng cách đặt từ khóa static trước khai báo
Là thành phần dữ liệu của lớp nhưng
Các đối tượng của lớp đều dùng chung thành phần tĩnh này
Theo đối tượng (cách thông thường)
Trang 1984
6 Thành phần tĩnh
a Dữ liệu tĩnh
Chú ý:
Tồn tại ngay khi chưa có đối tượng nào
Phải được khởi tạo trước khi đối tượng phát sinh
Phải khởi tạo ngoài lớp theo cú pháp:
static int count; //Đếm số đt được tạo ra
public : counter ();
cout<<"++Tao : bay gio co "<<++count<<" doi tuong\n";
} counter:: ~counter () {
cout<<" Xoa : bay gio con "<< count<<" doi tuong\n";
6 Thành phần tĩnh
b Phương thức tĩnh Khái niệm:
Là hàm thành phần của lớp nhưng không gắn với đối tượng cụ thể nào
Dùng để thao tác chung cho lớp
Trong thân hàm không có đối tượng ẩn
Ví dụ: xây dựng lớp SV gồm phương thức nhập,
in 1 sinh viên Nhập, in danh sách sinh viên
static <kiểu DL trả về> <tên hàm>([tham số]);
Trang 2088
7 Thành phần hằng
a Dữ liệu hằng
Khái niệm:
là thành phần dữ liệu của lớp nhưng không
thay đổi giá trị trong quá trình tồn tại
Ví dụ: Với lớp nhân sự thì số CMT là thành phần
hằng
Khai báo:
Thành phần hằng không thể thay đối sau khi
đối tượng được hình thành
const <kiểu DL> <tên thành phần>;
Ví dụ: NhanSu(int k=0):scmt(k){…}
7 Thành phần hằng
b Phương thức hằng
Khái niệm:
là hàm thành phần của lớp nhưng không có khả
năng thay đổi thành phần DL trong đối tượng
Ví dụ: Với lớp PS thì phương thức in() là hằng
Lập trình hướng đối tượng (Object Oriented Programming - OOP)
Trang 2192
1 Khái niệm
Được thừa hưởng các thành phần từ một hay nhiều
lớp đã có (lớp cơ sở/Lớp cha – Based Class/parent
Trong lớp con ta có thể bổ sung thêm các thành
phần hoặc định nghĩa lại các thành phần
93
Ví dụ 2: Yêu cầu xây dựng 3 lớp
1 Khái niệm (tiếp)
Lớp ĐT mô tả các thực thể trong thế giới thực
Các đối tượng không độc lập nhau, chúng có
Thừa kế tạo ra mô hình phân cấp:
PS1
PS2
NGƯỜI
Mô hình Thừa kế tạo ra một quan hệ “is a”
Ví dụ: một đối tượng SV “là một” đối tượng thuộc lớp NGƯỜI
Trang 22Đơn Thừa kế : chỉ có một lớp cơ sở
Đa Thừa kế: có nhiều hơn một lớp cơ sở
97
2 Xây dựng lớp dẫn xuất
Cú pháp:
class <tên lớp con>:[kiểu dẫn xuất]<tên lớp cha1>
,[kiểu dẫn xuất]<tên lớp cha 2>…
{ // Các thành phần của lớp con };
3 Quyền truy xuất
(1) Quyền truy xuất tp đó ở lớp cha : (2) Kiểu dẫn xuất
private protected public
private private private private protected private protected protected public private protected public
(1) (2)
Quyền truy xuất ở lớp con
Trang 23102
4 Định nghĩa lại quyền truy xuất
Để định nghĩa lại:
Chỉ cần liệt kê thành phần đó sau từ khoá quyền
truy xuất tương ứng
<quyền truy xuất>: <tên lớp cha>::<tên tp>;
Chỉ có thể định lại quyền truy xuất theo đúng quyền
của thành phần đó trong lớp cha
Nếu trong lớp cơ sở có nhiều tp cùng tên nhưng khác
quyền truy xuất thì không thể định nghĩa lại
Nếu lớp con có một tp cùng tên thì tp của lớp con sẽ che phủ tp lớp cha
Muốn truy xuất phải viết tường minh
Xây dựng lớp TSA Thừa kế lớp TS
Bổ sung: điểm toán, lý, hoá, nhập, in
Trang 24106
5 Hàm khởi tạo và hàm huỷ
a Hàm khởi tạo
- Hàm khởi tạo của lớp cha không được Thừa kế
- Mỗi đối tượng của lớp con có thể coi là một đối
tượng của lớp cha
Do đó: khi gọi hàm khởi tạo của lớp con sẽ kéo theo
gọi hàm khởi tạo của lớp cha
Thứ tự gọi:
Hàm khởi tạo lớp cha Hàm khởi tạo lớp con
Ví dụ: hàm khởi tạo của lớp A, B
107
5 Hàm khởi tạo và hàm huỷ
Nếu xây dựng hàm khởi tạo của lớp con:
- Phải gọi hàm khởi tạo của lớp cha tường minh
Cú pháp
<hàm khởi tạo dẫn xuất>([t/số]):<hàm khởi tạo cơ sở>([t/số])
{ }
Chú ý:
Hàm khởi tạo lớp cơ sở thực hiện trước Nếu lớp dẫn xuất có nhiều lớp cơ sở thì trình tự thực hiện tuân theo trình tự Thừa kế
5 Hàm khởi tạo và hàm huỷ
b Hàm huỷ
Hàm huỷ của lớp cơ sở không được Thừa kế
Các hàm huỷ được thi hành theo trình tự
ngược lại so với hàm khởi tạo
Hàm huỷ của lớp dẫn xuất thi hành trước hàm
huỷ của lớp cơ sở
Lưu ý:
Hủy lớp con rồi mới hủy lớp cha
Tạo lớp cha rồi mới tạo lớp con
109
class DongVat {
protected: int sochan;
public:
DongVat() {cout<<“Tao dong vat”;}
DongVat (int sc) {sochan=sc; cout<<“Tao dong vat”;}
~ DongVat() {cout<<“Huy dong vat”;}
void keu(){cout<<“Khong”;}
};
Trang 25ConMeo() {cout<<“Tao con meo: ”;}
ConMeo(int sc, int ml, int ns): DongVat(sc)
~ ConMeo() {cout<<“Huy con meo”;}
void Keu() {cout<<“Meo meo…”;}
int Tinhtuoi() {…}
};
111
int main() {
6 Đa Thừa kế
Khái niệm
Là khả năng xây dựng lớp dẫn xuất Thừa kế từ
nhiều hơn một lớp cơ sở
Đa Thừa kế có thể là tính năng rất mạnh nhưng
đôi khi gây ra một số vấn đề
Lập trình hướng đối tượng
Trang 26114
1 Khái niệm về tính đa hình
Đa hình là khả năng cho phép 1 lời gọi đến 1 hàm
thuộc lớp con, nếu như đối tượng của lớp cha đang
giữ địa chỉ hoặc tham chiếu đến đối tượng thuộc
o Sử dụng con trỏ để truy cập tới hàm ảo
o Định nghĩa trong lớp cơ sở ngay cả khi nó không
3 Hàm thuần ảo (pure virtual function)
Khái niệm: là hàm ảo mà không có ĐN hàm
Trang 27118
3 Hàm thuần ảo (pure virtual function)-tt
Đặc điểm:
o Không thể khai báo đối tượng thuộc lớp có hàm
ảo thuần tuý
o Lớp có hàm ảo thuần tuý chỉ làm lớp cơ sở cho
lớp khác và gọi là lớp cơ sở trừu tượng
119
4 Lớp ảo (virtual class)
Là lớp chứa ít nhất 1 hàm thuần ảo
Lớp ảo không thể tạo ra đối tượng
Trang 28 Khi truy cập thành phần x trong C thì chương trình dịch
không biết thành phần x đó là của lớp A hay B
Gọi A là lớp cơ sở của lớp B và C
Gọi D là lớp dẫn xuất của lớp B và C
Khai báo tường minh
<tên đối tƣợng>.<tên lớp cơ sở>::<tên thành phần>;
Coi A là lớp cơ sở ảo của cả B và C
Khi đó trong D chỉ có một sự thể hiện của A
Khai báo:
class <lớp dẫn xuất>: virtual <kiểu dẫn xuất><lớp cơ sở>
Khi đó ta khai báo
class B: virtual public A{…}
class C: virtual public A{…}
5 Lớp cơ sở ảo (Virtual base class)
Trang 29Shape (float a = 1.0,float b = 1.0):x(a),y(b) {}
virtual float calArea() const = 0 ;
virtual float calPerimeter() const =0 ;
virtual void input(istream &) = 0 ;
virtual void output(ostream &) = 0 ;
virtual string whatshape() const = 0 ;
Circle(float r = 1.0) : Shape(r) {} Circle(Circle & s) { x = s.x;}
float calArea() const {return 3.14 * x * x;}
float calPerimeter() const {return 2 * 3.14 * x;}
void input( { cin >> x; } void output( ){ cout << x; } string whatshape() const { return "Circle"; }
Shape **p = new Shape * [4];
p[0] = new Circle(5);
p[1] = new Rectangle;
cin >> *p[1]; p[2] = new Square;
cin >> *p[2]; p[3] = new RTriangle(3, 7);
cout << “Max area is " << maxArea(p) << endl;
for (int i = 0; i < 4; i++) {
show(*p[i]);
delete p[i];
} delete [] p;
return 0;
}