Bài giảng Lập trình hướng đối tượng - Từ C đến C++

Các khác biệt đối với C (ngoài các đặc điểm

hướng đối tượng)

¨ Chú thích

¨ Các kiểu dữ liệu

¨ Kiểm tra kiểu, đổi kiểu

¨ Cảnh báocủa trình biêndịch

¨ Phạm vi và khai báo

¨ Không gian tên

¨ Hằng

¨ Quản lýbộ nhớ

¨ Tham chiếu

pdf16 trang | Chuyên mục: C/C++ | Chia sẻ: dkS00TYs | Lượt xem: 1860 | Lượt tải: 0download
Tóm tắt nội dung Bài giảng Lập trình hướng đối tượng - Từ C đến C++, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
rong một không gian tên
¨ không xung đột với các tên được
khai báo trong các không gian tên khác
¨ Tránh xung đột tên biến, tên hàm
¨ Nghiễm nhiên có thể được
liên kết ra ngoài (external linkage)
namespace Frog {
double weight;
double jump() {…}
}
namespace Kangaroo {
int weight;
void jump() {…}
}
@ 2004 Trần Minh Châu. FOTECH. VNU 13
Namespace
n Ví dụ
namespace Frog {
double weight;
double jump() {…}
}
namespace Kangaroo {
int weight;
void jump() {…}
}
int main()
{
Frog::weight = 5;
Kangaroo::jump();
}
weight trong namespace
Frog và weight trong
namespace Kangaroo độc
lập và không bị xung đột
Khi sử dụng định danh,
dùng tên namespace và
toán tử phạm vi
@ 2004 Trần Minh Châu. FOTECH. VNU 14
Namespace
n C++ cung cấp hai cơ chế để đơn giản hóa
việc sử dụng các namespaces: các khai
báo using và các định hướng using.
n khai báo using (using-declaration) cho
phép truy nhập một định danh cụ thể trong
vùng khai báo tạm thời
using ::;
¨Từ đây, ta có thể sử dụng tên mà không cần
mỗi lần đều phải chỉ rõ namespace chứa nó.
@ 2004 Trần Minh Châu. FOTECH. VNU 15
Namespace
n Ví dụ sử dụng khai báo using
namespace Frog {
double weight;
double jump() {…}
}
int main()
{
using Frog::weight;
int weight; // Error (already declared locally)
weight = 5; // Sets Frog::weight to 5
}
Từ đây, weight được
hiểu là Frog::weight
Khai báo using cho định
danh weight trong
namespace Frog.
@ 2004 Trần Minh Châu. FOTECH. VNU 16
Namespace
n Khai báo using dành cho 1 tên, định hướng
using cho phép truy nhập mọi định danh trong
namespace
using namespace ;
n Định hướng using thường được đặt tại mức
toàn cục.
#include 
using namespace std;
…
@ 2004 Trần Minh Châu. FOTECH. VNU 17
Quản lý bộ nhớ
n Cấp phát bộ nhớ động trong C trông rối rắm và dễ lỗi
¨ myObj* obj = (myObj*)malloc(sizeof(myObj));
n Các nhà thiết kế C++ thấy rằng:
¨ Một ngôn ngữ sử dụng class sẽ hay phải sử dụng bộ nhớ động.
¨ Không có lý do gì để tách cấp phát bộ nhớ động ra khỏi việc
khởi tạo đối tượng (hay tách thu hồi bộ nhớ động ra khỏi việc
hủy đối tượng)
n malloc và free đã được thay bằng new và delete
@ 2004 Trần Minh Châu. FOTECH. VNU 18
Quản lý bộ nhớ
n Lợi thế của new so với malloc:
¨ Không cần chỉ ra lượng bộ nhớ cần cấp phát
¨ Không cần đổi kiểu
¨ Không cần dùng lệnh if để kiểm tra xem bộ nhớ đã hết chưa
¨ Nếu bộ nhớ đang được cấp cho một đối tượng, hàm khởi tạo
(constructor) của đối tượng sẽ được gọi tự động (tương tự,
delete sẽ tự động gọi hàm hủy (destructor) của đối tượng)
n Ví dụ:
myObj* obj = new myObj; //một đối tượng
delete obj;
myObj* obj = new myObj[10]; // mảng đối tượng
delete[] obj;
@ 2004 Trần Minh Châu. FOTECH. VNU 19
Tham chiếu – Reference
n Tham chiếu tới một đối tượng là một biệt danh tới đối
tượng đó
n Có thể coi mọi thao tác trên tham chiếu đều được thực
hiện trên chính đối tượng nguồn.
int x = 5;
int& y = x;
cout << “x = “ << x << “ y = “ << y << “.\n”; // x = 5 y = 5
x = x + 1;
cout << “x = “ << x << “ y = “ << y << “.\n”; // x = 6 y = 6
y = y + 1;
cout << “x = “ << x << “ y = “ << y << “.\n”; // x = 7 y = 7
int *p = &y;
*p = 9;
cout << “x = “ << x << “ y = “ << y << “.\n”; // x = 9 y = 9
@ 2004 Trần Minh Châu. FOTECH. VNU 20
Tham chiếu – Reference
n Tham chiếu có thể được dùng độc lập nhưng thường hay được
dùng làm tham số cho hàm
n C truyền mọi đối số cho hàm bằng giá trị (truyền trị - call by value)
¨ Khi cần, ta có thể truyền một con trỏ tới đối tượng (chính nó cũng được
truyền bằng giá trị)
¨ void myFunction(myObj* obj) {…}
n C++ cho phép các đối số hàm được truyền bằng tham chiếu (call by
reference)
¨ void myFunction(myObj& obj) {…}
¨ myObj& có nghĩa “tham chiếu tới myObj”
¨ đối với các đối số là các đối tượng lớn, truyền bằng tham chiếu đỡ tốn
kém hơn truyền bằng giá trị (do chỉ truyền địa chỉ bộ nhớ)
@ 2004 Trần Minh Châu. FOTECH. VNU 21
Tham chiếu – Reference
n Ví dụ: tham chiếu làm đối số cho hàm
int f(int &i) { ++i; return i; }
int main() {
int j = 7; cout << f(j) << endl; cout << j <<
endl;
}
n Biến i là một biến địa phương của hàm f. i thuộc kiểu tham chiếu
int và được tạo khi f được gọi.
n Trong lời gọi f(j), i được tạo tương tự như trong lệnh
int &i = j;
n Do đó trong hàm f, i sẽ là một tên khác của biến j và sẽ luôn như
vậy trong suốt thời gian tồn tại của i
@ 2004 Trần Minh Châu. FOTECH. VNU 22
Tham chiếu – Reference
n Tham chiếu phải được khởi tạo
¨ int& x; // Error
n Giá trị của tham chiếu không được thay đổi sau khi đã khởi tạo
¨ không thể “chiếu” lại một tham chiếu tới đối tượng khác
¨ chú ý phân biệt giữa khởi tạo tham chiếu và gán trị cho tham chiếu
n Truy nhập tới tham chiếu chính là truy nhập tới đối tượng nguồn
¨ áp dụng cho cả toán tử & và phép gán
n cout << “The address of x is: “ << &x << “.\n”;
n cout << “The address of y is: “ << &y << “.\n”;
n Output:
n The address of x is 0x0056dc13.
n The address of y is 0x0056dc13.
@ 2004 Trần Minh Châu. FOTECH. VNU 23
Tham chiếu – Reference
n Vậy tại sao dùng tham chiếu thay cho con trỏ?
n Tham chiếu sạch hơn, không dễ gây lỗi như con trỏ, đặc biệt khi
dùng trong hàm
¨ tham chiếu đảm bảo không chiếu tới null
n Sử dụng tham chiếu trong nguyên mẫu hàm giúp cho việc gọi hàm
dễ hiểu hơn
¨ không cần dùng toán tử địa chỉ
void func1(int *pi) { (*pi)++; }
void func2(int &ri) { ri++; }
int main() {
int i = 1;
func1(&i); // call using address of i
func2(i); // call using i
}
@ 2004 Trần Minh Châu. FOTECH. VNU 24
Const
n Trong C, hằng được định nghĩa bằng định hướng tiền
xử lý #define
#define PI 3.14
¨ Biên dịch chậm hơn (trình tiền xử lý tìm và thay thế)
¨ Trình debug không biết đến các tên hằng
¨ Sử dụng #define không gắn được kiểu dữ liệu với giá trị hằng
(v.d. ‘15’ là int hay float?)
n Const của ANSI-C ít dùng hơn và có nghĩa hơi khác:
¨ ANSI-C const không được trình biên dịch chấp nhận là hằng
n Không dùng để khai báo mảng được
n In C++, const values can be used when declaring arrays:
@ 2004 Trần Minh Châu. FOTECH. VNU 25
Const
Hằng của ANSI-C và C++ có các quy tắc phạm vi khác
nhau
n Các giá trị #define có phạm vi file (do trình tiền xử lý
chỉ thực hiện tìm và thay thế tại file đó)
n const của ANSI-C được coi là các biến có giá trị không
đổi và có phạm vi chương trình
¨ Do đó ta không thể có các biến trùng tên tại hai file khác nhau 
n Trong C++, các định danh const tuân theo các quy tắc
phạm vi như các biến khác
¨ Do đó, chúng có thể có phạm vi toàn cục, phạm vi không gian
tên, hoặc phạm vi khối
@ 2004 Trần Minh Châu. FOTECH. VNU 26
const và con trỏ
n Ba loại:
1. const int * pi; // con trỏ tới hằng
2. int * const ri = &i; // hằng con trỏ
3. const int * const ri = &i; //hằng con trỏ tới hằng
n Các khái niệm cần ghi nhớ:
n Nếu một đối tượng là hằng
¨ Không thể sửa đối tượng đó
¨ Chỉ có con trỏ tới hằng mới được dùng để trỏ tới hằng, con trỏ
thường không dùng được
n Nếu PI được khai báo là con trỏ tới hằng:
¨ Có thể thay đổi PI, nhưng *PI không thể bị thay đổi.
¨ PI có thể trỏ đến hằng hoặc biến thường
@ 2004 Trần Minh Châu. FOTECH. VNU 27
const và con trỏ
n Khi sử dụng một con trỏ, có hai đối tượng có liên quan: chính con
trỏ đó và đối tượng nó trỏ tới
n Cú pháp cho con trỏ tới hằng và hằng con trỏ rất dễ nhầm lẫn
n Quy tắc: trong lệnh khai báo, từ khoá const bên trái dấu * có
nghĩa đối tượng được trỏ tới là hằng, từ khoá const bên phải dấu
* có nghĩa con trỏ là hằng
n Cách dễ hơn: đọc các khai báo từ phải sang trái
¨ char c = 'Y'; // c là char
¨ char *const cpc = &c; //cpc là hằng con trỏ tới char
¨ const char *pcc; // pcc là con trỏ tới hằng char
¨ const char *const cpcc = &c; // cpcc là hằng con trỏ tới
hằng char
@ 2004 Trần Minh Châu. FOTECH. VNU 28
hằng tham chiếu làm tham số hàm
Có hai lý do để truyền tham biến, nhưng nếu hàm được
truyền không cần sửa đối tượng được truyền thì ta
nên khai báo tham biến là const. Có hai ích lợi:
1. Nếu trong hàm, ta lỡ sửa đổi tham số thì trình biên
dịch sẽ bắt lỗi.
n ngăn chặn được một số lỗi lập trình viên có thể phạm
2. Ta có thể truyền các đối số là hằng hoặc không phải
hằng cho hàm có hằng tham biến
n Ngược lại, đối với các hàm có tham biến không phải là hằng,
ta không thể truyền hằng làm đối số.
@ 2004 Trần Minh Châu. FOTECH. VNU 29
hằng tham chiếu làm tham số
hàm
void non_constRef(LargeObj &Lo) { cout Lo.height; }
void constRef(const LargeObj &Lo) { cout Lo.height; }
int main {
LargeObj dinosaur; const LargeObj rocket;
non_constRef(dinosaur);
constRef(dinosaur);
non_constRef(rocket); // Error
constRef(rocket);
}
void non_constRef(LargeObj &Lo) { Lo.height +=10; } // Fine
void constRef(const LargeObj &Lo) { Lo.height +=10; } // Error
!!!
n Ví dụ Lỗi: Lo là hằngnên không
được sửa đổi
Lỗi: rocket là hằng,
nên không thể làm
đối số không phải hằng
@ 2004 Trần Minh Châu. FOTECH. VNU 30
const: Hàm thành viên
Đối với hàm thành viên không sửa dữ liệu của đối tượng
chủ, ta nên khai báo hàm đó là hằng hàm
¨ Đối với các đối tượng được khai báo là hằng, C++ chỉ cho phép
gọi các hàm thành viên là hằng mà không cho phép gọi các
hàm thành viên không phải là hằng của đối tượng đó.
class Date
{
int year, month, day;
public:
int getDay() const { return day; }
int getMonth() const { return month; }
void addYear(int y) // Non-const function
};
@ 2004 Trần Minh Châu. FOTECH. VNU 31
Const - Tóm tắt
Nên khai báo hằng đối với:
n Các đối tượng mà ta không định sửa đổi
const double PI = 3.14; 
const Date openDate(18,8,2003);
n Các tham số của hàm mà ta không định cho hàm đó sửa đổi
void printHeight(const LargeObj &LO)
{ cout << LO.height; }
n Các hàm thành viên không thay đổi đối tượng chủ
int Date::getDay() const { return day; }
Lưu ý: các yêu cầu trên áp dụng cho tất cả các bài tập, bài thi của môn học.

File đính kèm:

  • pdfBài giảng Lập trình hướng đối tượng - Từ C đến C++.pdf