trueclass
cout
C++operator
catch
virtual throw
try
friend bool
cinnew
inline private OOP
deleteusing falseSTL
public
1
T h S . Đ ặ n g B ì n h P h ư ơ n gd b p h u o n g @ f i t . h c m u s . e d u . v n
VCBB© 19.03a
this
Bộ môn Công nghệ phần mềm
Khoa Công nghệ thông tin
Trường Đại học Khoa học Tự nhiên
PP LT HƯỚNG ĐỐI TƯỢNG
THUỘC TÍNH ĐỐI TƯỢNG
& PHƯƠNG THỨC
2
VC
BB
1 2 3 4 5 6 7
Nội dung
Thuộc tính đối tượng và phương thức
Phương thức tạo lập (constructor)
Phương thức hủy (destructor)
Tham số của phương thức
Định nghĩa phép toán (operator) cho kiểu dữ liệu mới
Phương thức chuyển đổi kiểu dữ liệu (casting method)
Một số vấn đề liên quan khác
Mẫu thiết kế Singleton và áp dụng
#include <iostream>using namespace std;
void main(){
cout << “Hello World”;cout << endl;
3
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Nhu cầu
Thuộc tính đối tượng và phương thức
4
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Đặc điểm (trong NNLT C++)
Tên trùng với tên lớp và không có kiểu trả về.
Tự động thực thi khi đối tượng được tạo nhằm
khởi tạo dữ liệu và chuẩn bị những công việc
cần thiết để bắt đầu chu kỳ sống của đối tượng.
Có thể có nhiều phương thức tạo lập nạp chồng
nhau (overloading) được phân biệt theo quy tắc
như việc chồng các hàm (phân biệt nhờ danh
sách tham số truyền vào).
Thuộc tính đối tượng và phương thức
HủyTạo lập Sử dụng
5
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Phân loại
Phương thức tạo lập mặc định (default constructor)
Không có tham số đầu vào.
Được tự động tạo ra nếu lớp không có bất kỳ
phương thức tạo lập nào được định nghĩa.
Phương thức tạo lập sao chép (copy constructor)
Để tạo ra một đối tượng từ một đối tượng có sẵn.
Phương thức tạo lập người lập trình định nghĩa
Có thể quy định các tham số đầu vào khác
nhau để khởi tạo dữ liệu cho đối tượng.
Thuộc tính đối tượng và phương thức
6
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Cú pháp khai báo và định nghĩa
Khai báo phương thức tạo lập (tổng quát)
Định nghĩa phương thức tạo lập
Thuộc tính đối tượng và phương thức
1 class-name(param-list);
12345
class-name::class-name(param-list)
{
// Khởi tạo dữ liệu và chuẩn bị những công việc
// cần thiết để bắt đầu chu kỳ sống của đối tượng…
}
7
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Ví dụ
Khai báo lớp CFraction (tập tin Fraction.h)
Thuộc tính đối tượng và phương thức
1234567891011121314
#ifndef _FRACTION_H
#define _FRACTION_H
class CFraction
{
int m_nNum; // Tử số (numerator)
int m_nDenom; // Mẫu số (denominator)
public:
CFraction(); // Phương thức tạo lập mặc định
CFraction(int); // Phương thức tạo lập dạng tử/1
CFraction(int, int); // Phương thức tạo lập dạng tử/mẫu
};
#endif
8
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Ví dụ
Cài đặt lớp CFraction (tập tin Fraction.cpp)
Thuộc tính đối tượng và phương thức
1234567891011121314
#include “Fraction.h”
// Phương thức tạo lập mặc định (default constructor)
CFraction::CFraction() { m_nNum = 0; m_nDenom = 1; }
// Phương thức tạo lập dạng tử/1
CFraction::CFraction(int nNum) { m_nNum = nNum; m_nDenom = 1; }
// Phương thức tạo lập dạng tử/mẫu
CFraction::CFraction(int nNum, int nDenom)
{
if (nDenom < 0) { nNum = -nNum; nDenom = -nDenom; }
if (nDenom == 0) { nDenom = 1; }
m_nNum = nNum; m_nDenom = nDenom;
}
9
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Ví dụ
Một số khai báo hợp lệ
Thuộc tính đối tượng và phương thức
1234567891011121314
CFraction frac1; // ()
CFraction frac2(1506); // (int)
CFraction frac3(12, 8); // (int, int)
CFraction* pFrac1 = new CFraction; // new CFraction()
CFraction* pFrac2 = new CFraction(1506); // (int)
CFraction* pFrac3 = new CFraction(12, 8);// (int, int)
CFraction aFrac1[2]; // () x 2
CFraction aFrac2[2] = {2912, 1706}; // (int) x 2
CFraction aFrac3[2] = {CFraction(2912), CFraction(1706)};
CFraction aFrac4[2] = {CFraction(369), CFraction(156, 128)};
CFraction* paFrac = new CFraction[2]; // () x 2
10
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Phương thức tạo lập sao chép
Khái niệm
Khởi tạo đối tượng của một lớp dựa trên việc
sao chép một đối tượng sẵn có của lớp đó
(không áp dụng cho phép gán).
Được thực thi khi truyền hoặc trả về đối
tượng của lớp đó theo kiểu tham trị.
Ví dụ
Thuộc tính đối tượng và phương thức
12345
CFraction doSomething(CFraction frac) { /* Xử lý… */ }
CFraction frac1(82, 85), frac2;
CFraction frac3(frac1); // Khởi tạo frac3 từ frac1
CFraction frac4 = frac1; // Khởi tạo frac4 từ frac1
frac2 = doSomething(frac1); // Khởi tạo khi truyền và trả
11
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Phương thức tạo lập sao chép mặc định
Trong C++, phương thức tạo lập sao chép mặc
định (default copy constructor) được tự động
sinh ra cho lớp đối tượng do người lập trình tự
định nghĩa và giúp sao chép từng thành phần
thuộc tính (member-wise copy) từ đối tượng
nguồn sang đối tượng đích theo dạng từng bit
(bit-wise copy).
Nếu các thành phần dữ liệu là các kiểu con trỏ
thì quá trình sao chép sẽ chỉ sao chép địa chỉ của
con trỏ (shallow copy) chứ không thật sự sao
chép vùng nhớ mà chúng quản lý (deep copy).Thuộc tính đối tượng và phương thức
12
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Vùng nhớđã bị hủyVùng nhớ
chứa dữ liệu
Hình ảnh minh họa
Thuộc tính đối tượng và phương thức
: CFraction
- m_nNum: int
- m_nDenom: int
: CFraction
- m_nNum: int
- m_nDenom: int
: CDynamicArray
- m_nSize: int
- m_pData: int*
: CDynamicArray
- m_nSize: int
- m_pData: int*
13
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Cài đặt phương thức tạo lập sao chép
Khai báo phương thức tạo lập sao chép
Lưu ý
Nếu tham số được khai báo ở dạng tham trị
thì phương thức tạo lập sao chép lại được
kích hoạt để sao chép đối tượng này lỗi do
sử dụng phương thức đang được định nghĩa!
Việc sử dụng tham chiếu (&) kết hợp với
const (pass-by-reference-to-const) để đối
tượng không bị sao chép và bị thay đổi.
Thuộc tính đối tượng và phương thức
1 class-name(const class-name&);
14
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Cài đặt phương thức tạo lập sao chép
Ví dụ cài đặt cho lớp mảng động
Thuộc tính đối tượng và phương thức
12345678910111213
class CDynamicArray
{
int m_nSize;
int* m_panData;
public:
CDynamicArray(const CDynamicArray&);
};
CDynamicArray::CDynamicArray(const CDynamicArray& dynArr) {
m_nSize = dynArr.m_nSize;
m_panData = new int[m_nSize];
for (int i = 0; i < m_nSize; i++)
m_panData[i] = dynArr.m_pansData[i];
}
15
VC
BB
Phương thức tạo lập (constructor)1 2 3 4 5 6 7
Đối sánh giữa C++, Java và C#
Đọc thêm [OOP] trang 83-87.
Chuỗi phương thức tạo lập (constructor
chaining).
Phương thức tạo lập trong kế thừa.
Xử lý khi có lỗi trong phương thức tạo lập.
Phương thức tạo lập sao chép mặc định.
Phương thức tạo lập tĩnh.
Thuộc tính đối tượng và phương thức
16
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Nhu cầu
Thuộc tính đối tượng và phương thức
17
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Đặc điểm (trong NNLT C++)
Tên trùng với tên lớp và có dấu ~ ở phía trước.
Không có tham số đầu vào và giá trị trả về.
Mỗi lớp chỉ có duy nhất một phương thức hủy.
Tự động thực hiện mỗi khi đối tượng của lớp
bị hủy (hết phạm vi sử dụng).
Chỉ được thực hiện một lần duy nhất trong
chu kỳ sống của đối tượng.
Trình biên dịch sẽ tự động tạo phương thức hủy
mặc định (default destructor, không làm gì cả)
nếu lớp không có phương thức hủy nào.
Thuộc tính đối tượng và phương thức
18
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Cú pháp khai báo và định nghĩa
Khai báo phương thức hủy
Định nghĩa phương thức hủy
Thuộc tính đối tượng và phương thức
1 ~class-name();
1234
class-name::~class-name()
{
// Giải phóng tài nguyên đã cấp phát cho đối tượng…
}
19
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Ví dụ
Cài đặt phương thức hủy cho lớp mảng động
Thuộc tính đối tượng và phương thức
1234567891011121314
class CDynamicArray
{
int m_nSize;
int* m_panData;
public:
~CDynamicArray();
};
CDynamicArray::~CDynamicArray() {
if (m_nSize > 0)
{
m_nSize = 0;
delete []m_panData;
}
}
20
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Ví dụ
Cài đặt lớp CTimer
Thuộc tính đối tượng và phương thức
1234567891011121314
#include <ctime>
class CTimer
{
clock_t m_clockStart;
public:
CTimer() { m_clockStart = clock(); }
~CTimer()
{
clock_t clockEnd = clock();
cout << “Elapsed time: ” <<
(clockEnd – m_clockStart) << endl;
}
};
21
VC
BB
Phương thức hủy (destructor)1 2 3 4 5 6 7
Đối sánh giữa C++, Java và C#
Đọc thêm [OOP] trang 90.
Cơ chế “dọn rác” (garbage collector).
Nguy cơ khi quên hủy tài nguyên đã cấp phát.
Thuộc tính đối tượng và phương thức
22
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Tham số giá trị (tham trị)
Thuộc tính đối tượng và phương thức
int t = x;x = y;y = t;
…… 03 00 00 00 06 00 00 00
int a = 3
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
int b = 6
int x int yswap
……
18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25
int x int y
03 00 00 00 06 00 00 00
23
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Tham số con trỏ
Thuộc tính đối tượng và phương thức
int t = *px;*px = *py;*py = t;
……
int a = 3
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
int b = 6
int* px int* pyswap
……
18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25
int* px int* py
0B 00 00 00 0F 00 00 00
03 00 00 00 06 00 00 00
24
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Tham số tham biến (tham chiếu)
Thuộc tính đối tượng và phương thức
int t = x;x = y;y = t;
……
int a = 3
0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17
int b = 6
int &x int &yswap
05 00 00 00 06 00 00 00
25
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Giá trị mặc định cho các tham số
Xem lại Chương 1 – Phần 3. Vấn đề về giá trị
mặc định của tham số hàm.
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011
class CFraction
{
int m_nNum, m_nDenom;
public:
// CFraction(), CFraction(int), CFraction(int, int)
CPhanSo(int nNum = 0, int nDenom = 1)
{
if (nDenom == 0) { nDenom = 1; }
m_nNum = nNum; m_nDenom = nDenom;
}
};
26
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Số lượng tham số không biết trước
Xem lại Chương 1 – Phần 6. Vấn đề về hàm có
số lượng tham số không biết trước.
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011
class CDynamicArray
{
int m_nSize;
int* m_panData;
public:
CDynamicArray(int nValue, ...)
{
// Các thao tác khởi tạo mảng từ dãy các số nguyên
// được truyền vào hàm tạo…
}
};
27
VC
BB
Tham số của phương thức1 2 3 4 5 6 7
Đối sánh giữa C++, Java và C#
Đọc thêm [OOP] trang 107-110.
Tham trị và tham chiếu.
Thuộc tính đối tượng và phương thức
28
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Nhu cầu và cách thực hiện
Xem lại Chương 1 – Phần 7. Nhu cầu về ký hiệu
phép toán cho kiểu dữ liệu mới nhưng là các
phương thức toán tử thực hiện trên các đối
tượng của lớp (class) thay vì là các hàm toán tử
thực hiện trên biến có kiểu cấu trúc (struct).
Nếu viết toán tử bên trong lớp và toán hạng thứ
nhất là đối tượng thuộc lớp đó thì không liệt kê
trong danh sách tham số của toán tử. Ngược lại
phải liệt kê và sử dụng từ khóa friend để có
thể truy cập các thành phần riêng của đối tượng.
Thuộc tính đối tượng và phương thức
29
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Hàm bạn (friend function) trong C++
Khái niệm
Hàm không phải thành viên của lớp nhưng có
thể truy cập các thành viên riêng của lớp đó.
Được định nghĩa như một hàm bình thường
nhưng bên trong khai báo lớp mà hàm làm
bạn sẽ có nguyên mẫu hàm (prototype) bắt
đầu bằng từ khóa friend.
Thuộc tính đối tượng và phương thức
12345
return-type func-name(param-list) { /* … */ }
class CFriendTest
{
friend func-name(param-list);
};
30
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Hàm bạn (friend)
Khái niệm
Hàm không phải thành viên của lớp nhưng có
thể truy cập các thành viên riêng của lớp đó.
Được định nghĩa như một hàm bình thường
nhưng bên trong khai báo lớp mà hàm làm
bạn sẽ có nguyên mẫu hàm (prototype) bắt
đầu bằng từ khóa friend.
Thuộc tính đối tượng và phương thức
12345
class CFriendTest
{
friend func-name(param-list);
};
return-type func-name(param-list) { /* … */ }
31
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Hàm bạn (friend)
Lưu ý
Hữu ích khi quá tải toán tử hoặc truy cập các
thành viên riêng của hai hay nhiều lớp khác
nhau (hàm là friend của hơn một lớp).
Hàm friend không phải là thành viên của lớp
mà nó làm bạn mà chỉ là hàm thường, do đó:
• Khi định nghĩa hàm không sử dụng toán tử ::
• Không thể gọi hàm bằng cách dùng tên đối tượng
và toán tử truy cập thành viên (toán tử . hoặc ->).
• Không có con trỏ this trong hàm.
• Không thể được kế thừa.Thuộc tính đối tượng và phương thức
32
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Ví dụ
Toán tử + được viết bên trong lớp
Thuộc tính đối tượng và phương thức
1234567891011121314
class CFraction
{
int m_nNum, m_nDenom;
public:
const CFraction operator+(const CFraction&);
};
const CFraction CFraction::operator+(const CFraction& fracR)
{
CFraction fracResult;
fracResult.m_nNum = this->m_nNum * fracR.m_nDenom
+ fracR.m_nNum * this->m_nDenom;
fracResult.m_nDenom = this->m_nDenom * fracR.m_nDenom;
return fracResult;
}
33
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Ví dụ
Toán tử + được viết bên ngoài lớp
Thuộc tính đối tượng và phương thức
1234567891011121314
class CFraction
{
int m_nNum, m_nDenom;
public:
friend const CFraction operator+(const CFraction&, const CFraction&);
};
const CFraction operator+(const CFraction& fracL, const CFraction& fracR)
{
CFraction fracResult;
fracResult.m_nNum = fracL.m_nNum * fracR.m_nDenom
+ fracR.m_nNum * fracL.m_nDenom;
fracResult.m_nDenom = fracL.m_nDenom * fracR.m_nDenom;
return fracResult;
}
34
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Các toán tử có và không thể nạp chồng
Thuộc tính đối tượng và phương thức
Danh sách các toán tử có thể nạp chồng
cho kiểu dữ liệu mới do người lập trình tự định nghĩa
+ - * / % ^ &
| ~ ! = < > +=
-= *= /= %= ^= &= |=
<< >> >>= <<= == != <=
>= && || ++ -- ->* ,
-> [] () new new[] delete delete[]
Danh sách các toán tử không thể nạp chồng
cho kiểu dữ liệu mới do người lập trình tự định nghĩa
Một số toán tử của C . ?: sizeof
Một số toán tử của C++ :: .* typeid
35
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số quy ước và lời khuyên
Chỉ viết toán tử khi cần thiết (ví dụ làm chương trình
dễ xử lý và dễ đọc hơn…) và phù hợp với thực tế
(ví dụ toán tử nhân 2 ngày với nhau!)
Đảm bảo tính chất của toán tử giống như các tính
chất của các kiểu dữ liệu cơ sở (ví dụ toán tử + thực
hiện phép… trừ!)
Đảm bảo tính nhất quán giữa các cặp toán tử (ví dụ
== và !=, ++ và ++(int), > và <, …)
Ưu tiên viết bên trong lớp nếu phải truy xuất đến
các thành phần thuộc tính của lớp. Ngược lại, ưu
tiên viết bên ngoài lớp.
Thuộc tính đối tượng và phương thức
36
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số quy ước và lời khuyên
Các toán tử 2 ngôi đối xứng thường được viết dưới
dạng hàm friend (ví dụ toán tử +, -, …)
Các toán tử lvalue phải được viết là phương thức
toán tử non-static ở bên trong lớp (ví dụ toán tử =,
[], (), ->, *=, ++, …)
Sử dụng tham chiếu const cho các đối tượng có
kích thước lớn.
Sử dụng toán tử () để truy xuất phần tử trong ma
trận nhiều chiều.
Tận dụng các phương thức tạo lập một tham số
phục vụ việc ép kiểu ngầm định.
Thuộc tính đối tượng và phương thức
37
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử gán
C++ tự động cung cấp toán tử gán mặc định
cho lớp đối tượng mới.
Chỉ được gán 2 đối tượng cùng lớp.
Thực hiện theo cơ chế member-wise copy từ
đối tượng nguồn sang đối tượng đích theo
dạng bit-wise copy, do đó cần phải nạp chồng
khi thành phần dữ liệu là các biến con trỏ
sử dụng cấp phát bộ nhớ động.
Không dùng hàm friend khi nạp chồng.
Thuộc tính đối tượng và phương thức
38
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Cài đặt toán tử gán cho lớp mảng cấp phát động
Thuộc tính đối tượng và phương thức
12345678910111213
public:
CDynamicArray& operator=(const CDynamicArray& dynArr)
{
if (this != &dynArr) // Tránh gán chính nó
{
delete []m_pnData; // Xóa vùng nhớ đang giữ
m_nSize = dynArr.m_nSize;
m_pnData = new int[m_nSize];
for (int i = 0; i < m_nSize; i++)
m_pnData[i] = dynArr.m_pnData[i];
}
return *this;
}
39
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử chèn (insertion) <<
Thuộc tính đối tượng và phương thức
123456789101112
class CFraction
{
int m_nNum, m_nDenom;
public:
friend ostream& operator<<(ostream&, const CFraction&);
};
ostream& operator<<(ostream& os, const CFraction& frac)
{
os << frac.m_nNum << “/” << frac.m_nDenom;
return os;
}
40
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử trích (extraction) >>
Thuộc tính đối tượng và phương thức
123456789101112
class CFraction
{
int m_nNum, m_nDenom;
public:
friend istream& operator>>(istream&, CFraction&);
};
istream& operator>>(istream& is, CFraction& frac)
{
is >> frac.m_nNum >> frac.m_nDenom;
return is;
}
41
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử + viết sai (khác toán tử + gốc)
Thuộc tính đối tượng và phương thức
12345678910111213
class CFraction
{
int m_nNum, m_nDenom;
public:
friend void operator+(CFraction&, const CFraction&);
};
void operator+(CFraction& fracL, const CFraction& fracR)
{
fracL.m_nNum = fracL.m_nNum * fracR.m_nDenom
+ fracR.m_nNum * fracL.m_nDenom;
fracL.m_nDenom = fracL.m_nDenom * fracR.m_nDenom;
}
42
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử ++ sau viết sai (khác toán tử ++ gốc)
Thuộc tính đối tượng và phương thức
123456789101112
class CFraction
{
int m_nNum, m_nDenom;
public:
CFraction& operator++(int); // Toán tử ++ sau
};
CFraction& CFraction::operator++(int)
{
m_nNum = m_nNum + m_nDenom;
return *this;
}
43
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Một số ví dụ minh họa
Toán tử ++ sau viết đúng (giống toán tử ++ gốc)
Thuộc tính đối tượng và phương thức
12345678910111213
class CFraction
{
int m_nNum, m_nDenom;
public:
CFraction& operator++(int); // Toán tử ++ sau
};
CFraction& CFraction::operator++(int)
{
CFraction fracResult = *this;
m_nNum = m_nNum + m_nDenom; // ++(*this);
return fracResult;
}
44
VC
BB
Định nghĩa phép toán (operators) cho kiểu dữ liệu mới1 2 3 4 5 6 7
Đối sánh giữa C++, Java và C#
Đọc thêm [OOP] trang 99-100.
Các quy định nạp chồng toán tử.
Các toán tử có thể nạp chồng.
Thuộc tính đối tượng và phương thức
45
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Khái niệm và phân loại
Khái niệm
Ép kiểu (casting) là việc chuyển đổi các biến
từ kiểu dữ liệu này sang kiểu dữ liệu khác.
Phân loại (trong NNLT C++)
Ép kiểu ngầm định (implicit casting)
Ép kiểu chỉ định (explicit casting)• Ép kiểu theo chuẩn C (C-style casting), ép kiểu tĩnh (static_cast),
ép kiểu động (dynamic_cast), ép kiểu hằng (const_cast)
và ép kiểu dịch lại (reinterpret_cast)
Phương thức ép kiểu tự định nghĩa• Ép kiểu bằng phương thức tạo lập và ép kiểu bằng toán tử.
Thuộc tính đối tượng và phương thức
46
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Ép kiểu ngầm định
Sự tăng cấp (kiểu dữ liệu) trong biểu thức (chỉ
chuyển đổi tạm thời, nội bộ)
Các thành phần cùng kiểu thì kết quả là kiểu
chung, ví dụ:
• 2 / 4 => 0 (int / int => int)
• 2.0 / 4.0 => 0.5 (float / float => float)
Các thành phần khác kiểu thì kết quả là kiểu
bao quát nhất (char < int < long < float <
double), ví dụ:
• 2.0 / 4 => 2.0 / 4.0 => 0.5
(float / int => float / float => float)Thuộc tính đối tượng và phương thức
47
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Ép kiểu ngầm định
Trong phép gán, biểu thức ở vế phải luôn được
tăng cấp (hay giảm cấp) tạm thời cho giống biểu
thức ở vế trái và có thể làm mất tính chính xác
của số nguyên khi chuyển sang số thực!
Thuộc tính đối tượng và phương thức
123456
int i, j = 3;
float f = 1.23;
i = f; // f tạm thời giảm cấp thành int
f = i; // i tạm thời nâng cấp thành float
f = j; // j tạm thời nâng cấp thành float, f = 2.999995
48
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Ép kiểu chỉ định
Xem chi tiết trong [OOP] trang 110-119.
Ép kiểu theo chuẩn C (C-style casting).
Ep kiểu tĩnh (static_cast).
Ép kiểu động (dynamic_cast).
Ép kiểu hằng (const_cast).
Ép kiểu dịch lại (reinterpret_cast).
Thuộc tính đối tượng và phương thức
49
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Phương thức ép kiểu tự định nghĩa
Ép kiểu bằng phương thức tạo lập (1 tham số)
Thuộc tính đối tượng và phương thức
1234567891011121314
class CFraction
{
int m_nNum, m_nDenom;
public:
CFraction() { m_nNum = 0; m_nDenom = 1; }
CFraction(int nNum) { m_nNum = nNum; m_nDenom = 1; }
// Các phương thức khác…
};
void main()
{
CFraction frac1 = 2912; // CFraction(2912)
CFraction frac2; // CFraction()
frac2 = 1706; // CFraction(1706), operator=
}
50
VC
BB
Phương thức chuyển đổi kiểu dữ liệu (casting methods)1 2 3 4 5 6 7
Phương thức ép kiểu tự định nghĩa
Ép kiểu dữ liệu bằng toán tử
Thuộc tính đối tượng và phương thức
1234567891011121314
class CFraction
{
int m_nNum, m_nDenom;
public:
CFraction(int nNum, int nDenom) { m_nNum = nNum; m_nDenom = nDenom; }
operator int() const { return m_nNum / m_nDenom; }
};
void main()
{
CFraction frac(2912, 1706);
int nResult1 = frac; // Ép kiểu ngầm định
int nResult2 = int(frac); // Ép kiểu chỉ định
int nResult3 = (int)frac; // Ép kiểu chỉ định
}
51
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Thành phần tĩnh (static)
Khái niệm
Thành phần dữ liệu tĩnh (static data member
hay class-level member) và phương thức tĩnh
(static method hay class-level method) của
lớp không phụ thuộc vào một đối tượng cụ
thể nào cả mà là thành phần chung cho tất cả
các đối tượng của lớp tương ứng.
Cú pháp
Thuộc tính đối tượng và phương thức
12
static type-name var-name;
static return-type method-name(param-list);
52
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Thành phần tĩnh (static)
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011121314
class CStaticTest
{
static int s_nCount; // Số lượng đối tượng
public:
static int getCount() { return s_nCount; }
CStaticTest() { ++s_nCount; }
~CStaticTest() { --s_nCount; }
};
int CStaticTest::s_nCount = 0; // Bỏ từ khóa static
void main()
{
CStaticTest staticTest1, staticTest2;
cout << “Number of objects: ” << CStaticTest::getCount();
}
53
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Thành phần dữ liệu có kiểu là lớp
Khi A có thành phần dữ liệu là một đối tượng có
kiểu thuộc lớp B thì:
Khi A được tạo lập Phương thức tạo lập
của lớp B được thực hiện trước.
Khi A bị hủy Phương thức hủy của lớp B
được thực hiện sau.
Ký hiệu UML (quan hệ association)
Thuộc tính đối tượng và phương thức
BA
- b: B
54
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Thành phần dữ liệu có kiểu là lớp
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011121314
class CB
{
public:
CB() { cout << “Constructing CB...” << endl; }
~CB() { cout << “Destructing CB...” << endl; }
};
class CA
{
CB m_b;
public:
CA() { cout << “Constructing CA...” << endl; }
~CA() { cout << “Destructing CA...” << endl; }
};
void main() { CA a; }
55
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Danh sách khởi tạo (initializers)
Khái niệm
Khởi tạo giá trị cho các thành phần dữ liệu
của lớp (thứ tự thực hiện trong khai báo lớp).
Là cách duy nhất được sử dụng trong các
trường hợp không thể tạo lập giá trị ban đầu
cho các thành phần dữ liệu có kiểu hằng số,
tham chiếu hay đối tượng của lớp không có
phương thức tạo lập mặc định.
Cú pháp
Thuộc tính đối tượng và phương thức
1 class-name(param-list) : var-name-1(arg), var-name-2(arg)
56
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Danh sách khởi tạo (initializers)
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011121314
class CA
{
int m_nX;
public:
CA(int nX) { m_nX = nX; }
};
class CTest
{
const int m_nK;
CA& m_aRef;
CA m_a;
public:
CTest(int nK, A& aRef) : m_nK(nK), m_aRef(aRef), m_a(nK) { };
};
57
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Phương thức có thuộc tính const
Khái niệm
Cam kết sẽ không làm thay đổi trạng thái hay
giá trị của các thành phần dữ liệu của lớp.
Đối tượng bình thường có thể gọi được
phương thức bình thường hoặc const.
Đối tượng const có thể gọi phương thức
const nhưng không thể gọi phương thức
bình thường.
Cú pháp
Thuộc tính đối tượng và phương thức
1 return-type method-name(param-list) const;
58
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Phương thức có thuộc tính const
Ví dụ
Thuộc tính đối tượng và phương thức
1234567891011121314
class CA
{
public:
void test() { }
void testConst() const { }
};
void doSomething(CA a1, const CA& a2)
{
a1.test(); // OK, a1 non-const
a1.testConst(); // OK, a1 non-const
a2.test(); // Lỗi, a2 const, test() non-const
a2.testConst(); // OK, testConst() const
}
59
VC
BB
Một số vấn đề liên quan khác1 2 3 4 5 6 7
Luật bộ ba (rule of three)
Luật bộ ba (“rule of three”, “the Law of The Big
Three” hay “The Big Three”), được Marshall
Cline đề xuất năm 1991, là quy tắc trong C++
nói rằng “nếu một lớp đối tượng định nghĩa lại
một trong ba phương thức gồm phương thức
hủy – tạo lập sao chép – toán tử gán thì lớp đối
tượng này nên định nghĩa luôn cả ba phương
thức đó một cách tường minh”.
Thường được áp dụng trong các lớp đối tượng
có thuộc tính thành viên là con trỏ sử dụng bộ
nhớ được cấp phát động.Thuộc tính đối tượng và phương thức
60
VC
BB
Áp dụng1 2 3 4 5 6 7
Mẫu thiết kế Singleton và áp dụng
Mẫu thiết kế (design pattern)
Là lời giải mẫu cho các bài toán giống nhau.
Cuốn sách nổi tiếng “Design Patterns –
Elements of Reusable Object-Oriented
Software (năm 1994)
• Nhóm 4 tác giả (Gang of Four
– GoF) bao gồm Erich Gamma,
Richard Helm, Ralph Johnson
và John Vlissides.
• Gồm 23 mẫu thiết kế
(được gọi là mẫu GoF).
Thuộc tính đối tượng và phương thức
61
VC
BB
Áp dụng1 2 3 4 5 6 7
Mẫu thiết kế Singleton và áp dụng
Khái niệm
Là mẫu thiết kế trong lập trình hướng.
Áp dụng mẫu này lên một lớp sẽ đảm bảo
lớp này chỉ có nhiều nhất một đối tượng
được tạo ra trong suốt chương trình.
Sơ đồ UML
Thuộc tính đối tượng và phương thức
CSingelton
- static CSingleton s_pInstance
- CSingleton()
+ getInstance(): CSingleton
CSingleton getInstance()
{
return s_pInstance;
}
62
VC
BB
Áp dụng1 2 3 4 5 6 7
Mẫu thiết kế Singleton và áp dụng
Ý tưởng cài đặt (các vấn đề cần giải quyết)
Đặt các phương thức tạo lập dạng privateđể người dùng không thể tự ý tạo đối tượng
mới (phải định nghĩa phương thức tạo lập để
tránh sử dụng phương thức tạo lập mặc định)
Tạo sẵn một đối tượng CSingleton duy nhất
(nếu có) ở dạng static để người dùng chỉ
được phép sử dụng đối tượng đã có sẵn này
(lấy đối tượng thông qua một phương thức
static mà ta cung cấp).
Thuộc tính đối tượng và phương thức
63
VC
BB
Áp dụng1 2 3 4 5 6 7
Mẫu thiết kế Singleton và áp dụng
Cài đặt (nên chia mã nguồn thành nhiều tập tin)
Thuộc tính đối tượng và phương thức
1234567891011121314
class CSingleton
{
static CSingleton* s_pInstance; // Đối tượng duy nhất
CSingleton() { } // Phương thức tạo lập
public:
static CSingleton* getInstance();
};
CSingleton* CSingleton::s_pInstance = NULL;
static CSingleton* getInstance() // Phương thức lấy
{ // đối tượng của lớp
if (s_pInstance == NULL) s_pInstance = new CSingleton();
return s_pInstance;
}
void main() { CSingleton* pObj = CSingleton::getInstance(); }
64
VC
BB
Áp dụng1 2 3 4 5 6 7
Mẫu thiết kế Singleton và áp dụng
Thảo luận về các ứng dụng trong thực tế và
biến thể “Multi”-ton của mẫu Singleton.
Thuộc tính đối tượng và phương thức
65
VC
BB
1 2 3 4 5 6 7
Một số thuật ngữ
bitwise copy: tương tự như member-wise copy.
casting: ép kiểu.
const casting: ép kiểu hằng
constructor: phương thức tạo lập.
C-style casting: ép kiểu theo chuẩn C.
deep copy: khác với shallow copy, sao chép đầy đủ các thành
phần (kể cả sao chép các vùng nhớ mà các thành phần con trỏ
đang trỏ tới).
default constructor: phương thức tạo lập mặc định.
design pattern: mẫu thiết kế.
destructor: phương thức hủy.
dynamic casting: é kiểu động.
explicit casting: ép kiểu chỉ định.
Thuộc tính đối tượng và phương thức
66
VC
BB
1 2 3 4 5 6 7
Một số thuật ngữ
formal argument: tham số hình thức (gọi tắt là tham số).
implicit casting: ép kiểu ngầm định.
initializers: danh sách khởi tạo cho phương thức tạo lập.
member-wise copy: sao chép các thành viên.
operator: toán tử.
reinterpret casting: ép kiểu dịch lại.
shallow copy: tương tự như member-wise copy.
static casting: ép kiểu tĩnh.
static constructor: phương thức tạo lập tĩnh.
static member, class-level member: thành phần tinh của lớp,
chung cho mọi đối tượng của lớp.
static method, class-level method: phương thức tĩnh của lớp,
phương thức chung cho mọi đối tượng của lớp.
virtual method: phương thức ảo.Thuộc tính đối tượng và phương thức
67
VC
BB
1 2 3 4 5 6 7
Tài liệu tham khảo
[OOP] Chương 3 – Thuộc tính đối tượng và
phương thức (trang 76-134)
[Primer] Chapter 10 – Objects and Classes
Class Constructors and Destructors (trang 463-476)
Knowing Your Objects: The this Pointer (trang 477-482)
[Primer] Chapter 11 – Working with Classes
Operator Overloading & Introducing Friends(trang 502-541)
Automatic Conversions and Type Casts
for Classes (trang 541-556)
[Primer] Chapter 15 – Friends, Exceptions, and More
Type Cast Operators (trang 848-852)
Thuộc tính đối tượng và phương thức
68
VC
BB
1 2 3 4 5 6 7
Bài tập
Bài tập 4.1: Cài đặt lớp đồng hồ bấm giờ để xác
định thời gian (số giây) trôi qua (CStopWatch)
hỗ trợ một số hành động như sau:
Tự động thiết lập thời gian ban đầu bằng 0.
Bắt đầu (start), dừng hẳn (stop), tạm dừng
(pause), tiếp tục (resume) tính thời gian trôi qua.
Hiển thị (show) thời gian đã trôi qua ở lần gần
nhất (tự động gọi mỗi khi pause và stop).
Tự động hiển thị thời gian đã trôi qua từ khi
bắt đầu sinh ra đến khi khi đối tượng bị hủy.
Thuộc tính đối tượng và phương thức
69
VC
BB
1 2 3 4 5 6 7
Bài tập
Bài tập 4.2 đến 4.6: Bổ sung các phương thức
tạo lập, phương thức hủy thích hợp và nạp
chồng các toán tử cơ bản cho các bài tập:
2.6: Lớp phân số (CFraction).
2.7: Lớp đơn thức (CMonomial).
2.10: Lớp ngày (CDate).
3.1: Lớp học sinh (CStudent) sử dụng lớp
string.
3.2: Lớp mảng (CDynamicArray) sử dụng lớp
vector.
Thuộc tính đối tượng và phương thức
70
VC
BB
1 2 3 4 5 6 7
Bài tập
Bài tập 4.7: Xây dựng lớp số phức (CComplex)
hỗ trợ một số phương thức cơ bản (bao gồm
các phương thức tạo lập và phương thức hủy)
và nạp chồng các toán tử cơ bản.
Bài tập 4.8: Cài đặt lớp các thuật toán sắp xếp
tăng dần các số thực (CSingleSortAlgorithm)
chỉ cho phép thực hiện một phương pháp
sắp xếp đã chọn cho toàn bộ chương trình.
Bài tập 4.9: Cài đặt lớp cung cấp các thuật toán
sắp xếp tăng dần không cần tạo ra đối tượng
khi sử dụng (CStaticSortAlgorithm).Thuộc tính đối tượng và phương thức