You are on page 1of 5

Chương 2 :

Khai báo và định nghĩa :

Các bước của chương trình dịch


- Preprocessor làm nhiệm vụ xử lý các chỉ thị tiền xử lý (#define, macro...)
- Compile : Xử lý từng file mã nguồn :
Chia làm hai giai đoạn :
Giai đoạn 1 : có nhiệm vụ phân tích các câu lệnh thành cấu trúc cây, kiểm tra
tương thích kiểu...
Giai đoạn 2 : Dịch cấu trúc cây thành mã lệnh assem hoặc mã máy, tạo ra file .obj
của file mã nguồn.
- Linker : Liên kết các file obj, sửa các tham chiếu giữa các file, đảm bảo tính duy
nhất của một định nghĩa giữa các file...
Có hai kiểu liên kết :
- Internal linkage : Vùng nhớ cho biến, đối tượng được cấp phát trong vùng nhớ
dành cho file trong đó đối tượng được khai báo. Vì vậy biến, đối tượng chỉ có ý
nghĩa trong file.
- External linkage : Vùng nhớ dành cho biến, đối tượng được cấp phát trong vùng
nhớ chung của chương trình. Do đó biến, đối tượng có thể được tham chiếu ở các
file khác bằng một khai báo và không được khai báo external linkage hai lần trở
lên cho cùng một biến, đối tượng.

Khi định nghĩa một biến hay đối tượng phải chỉ rõ cách thức liên kế đối tượng đó (thường
có giá trị mặc định) bằng cách thêm từ khoá extern hoặc static (external hay internal).

Chương 5 : Thực hiện ẩn.


Các từ khoá : public, protected, private.
Uu điểm : che dấu những phần không cần thiết, chỉ cho phép người sử dụng thư viện sử
dụng giao diện được cung cấp, không cho phép tác động đến những thành phần có thể
làm ảnh hưởng đến cơ chế hoạt động bên trong, giảm thiểu ảnh hưởng của việc thay đổi
cơ chế hoạt động đến các chương trình sử dụng thư viện; bảo vệ bản quyền.

Chương 6 : Hàm tạo và hàm huỷ.


Khi một đối tượng được tạo (cấp phát bộ nhớ) chắc chắn ít nhất một hàm tạo của lớp
tương ứng sẽ được gọi.
Hàm tạo mặc định sẽ tự động được tạo bởi trình biên dịch nếu và chỉ nếu không một hàm
tạo nào khác được khai báo.
Hàm huỷ được gọi ngay cả khi chúng ta dùng goto để thoát ra khỏi phạm vi khai báo đối
tượng (nhưng không được gọi nếu dùng setjmp() và longjmp)

Chương 7 : Chồng hàm và hàm có đối số mặc định :


Chồng hàm dùng khi thực hiện cùng một chức năng với nhiều đối tượng khác nhau trong
khi hàm với tham số mặc định dùng khi một số tham số của hàm có tần suất suất hiện
(trong các lời gọi hàm) với một số giá trị nhất định cao hơn so với các giá trị khác; các
giá trị đó sẽ đựơc để là giá trị mặc định của tham số để rút gọn lời gọi hàm.
Chương 8 : Hằng số
Với C++, hằng số khai báo bằng const có thể được hoặc không được cấp phát bộ nhớ tuỳ
vào cách thức sử dụng hằng số đó của người sử dụng. Nếu không được cấp phát bộ nhớ,
một hằng const sẽ gần giống với một hằng #define (hằng #define được xử lý ở giai đoạn
preprocessor trong khi hằng const được xử lý ở giai đoạn compile). Nếu hằng const được
cấp phát bộ nhớ, giá trị của nó có thể không được biết đến cho đến ở giai đoạn compile
và do đó có thể phát sinh lỗi khi sử dụng hằng trong khai báo các biến hay đối tượng
khác. VD : không thể khai báo
const a[5] = {1,2,3,4,5}
float f[a[1]] // sai vì giá trị của a[1] không được biết đến khi compile
Vì chế độ liên kết mặc định của một hằng const khai báo ngoài các hàm là internal
linkage (chỉ đựơc liên kết trong phạm vi file) nên nếu hai file khác nhau cùng khai báo
một hằng const sẽ không bị báo lỗi khi liên kết với nhau. Nếu muốn sử dụng một hằng ở
nhiều file thì phải xác định external linkage khi khai báo bằng cách thêm từ khoá extern.
VD : extern const int buffersize = 100; // file 1
extern const buffersize; // file 2
(việc gán giá trị sẽ phân biệt giữa định nghĩa và khai báo hằng, mặc định các biến toàn
cục, các hàm toàn cục và các lớp được khai báo external linkage nên không cần dùng từ
khóa extern, nếu muốn đổi thành internal linkage phải thêm từ khoá static vào đầu).
Các trường hợp hằng const được cấp phát bộ nhớ :
- Mảng hằng hay hằng của các lớp có cấu trúc phức tạp (do cấu trúc symbol table
không chứa được các cấu trúc phức tạp)
- Cần tính toán địa chỉ của hằng (truyền cho các hàm...)
- Cần dùng trong nhiều file khác nhau.
Chú ý : Khai báo const chỉ nhằm để compiler tránh không cho thay đổi giá trị của biến
hay gán giá trị con trỏ đến biến đó trong mã chương trình; lúc chạy nếu hằng const đựơc
cấp phát vùng nhớ, vẫn có thể thay đổi được.
VD :
int d = 1;
const int* x = &d;
*x = 2 // lỗi biên dịch vì x là con trỏ trỏ đến một biến hằng.
d = 2 // không lỗi

Hằng trong lớp :


Trong lớp hằng const luôn đựơc cấp phát bộ nhớ. Khi định nghĩa hằng const trong lớp,
không được gán giá trị ngay tại thời điểm định nghĩa mà phải khởi tạo giá trị toàn bộ các
hằng const thông qua danh sách khởi tạo của hàm tạo (constructor initializer list), sau đó
chúng ta không đựơc phép thay đổi giá trị của hằng. Mỗi đối tượng của lớp có thể có một
giá trị khác nhau của cùng một hằng const.
VD :
class A
{
const int i, j; // không được gán giá trị khởi tạo ở đây
public :
A(int n = 0, int m = 0) : i(n), j(m) {};
};
Ngoài việc trả về giá trị hằng, từ khoá const còn dùng để khai báo các hàm hằng của lớp,
tức là các hàm được phép gọi khi khái báo một đối tượng const thuộc lớp đó bằng cách
thêm từ khoá const vào cuối khai báo và vào trước cặp {} trong định nghĩa hàm đó (tức
là thêm cả hai nơi).
VD:
//: C08:ConstMember.cpp
class X {
int i;
public:
X(int ii);
int f() const;
};

X::X(int ii) : i(ii) {}


int X::f() const { return i; }

int main() {
X x1(10);
const X x2(20);
x1.f();
x2.f();
} ///:~

Để đảm bảo sự bất biến của đối tượng const, các hàm const không đựơc làm thay đổi giá
trị của các thuộc tính (trừ trường hợp thêm từ khoá mutable) hoặc gọi các hàm không
const. Tuy nhiên vẫn có thể vượt qua cản trở này của trình biên dịch bằng cách ép kiểu
của biến con trỏ this (bên trong hàm const biến này là biến hằng nên phải ép kiểu để
thành biến). VD : p = (A *) this, sau đó thông qua con trỏ p để thay đổi các thuộc tính;
hoặc khai báo từ khoá mutable cho những biến cho phép thay đổi bởi các hàm const.

Chương 9 : Hàm inline


Hàm inline dùng để thay thế macro, là hàm mà các lời gọi hàm sẽ được trình biên dịch
thay thế bởi mã lệnh của hàm.

Chương 10 : Tham chiếu và hàm tạo sao chép


Tham chiếu : là một kỹ thuật tương tự như con trỏ cho phép ánh xạ đến một vùng nhớ
bằng một biến kiểu tham chiếu. VD : int x = 10; int& a = x; Khi đó mọi tác động vào a
cũng tác động vào x và ngược lại.
Tham chiếu thường đựơc dùng trong truyền tham số dưới dạng tham biến và trả về giá trị
của hàm. VD : Nếu khai báo int f(int& x); thì trong thân hàm f ta có thể thay đổi giá trị
của biến x và giá trị của tham số thật truyền vào cũng thay đổi theo.
Khi khai báo tham số có kiểu tham chiểu, ta không thể truyền một giá trị hằng làm tham
số vì trong hàm có thể thay đổi giá trị của tham chiếu và do đó thay đổi cả giá trị tham số
thật. Khi dó ta phải dùng tham chiếu hằng : int f(const int & x); và có khả năng truyền cả
biến và hằng làm tham số : f(12)...

Hàm khởi tạo sao chép được gọi khi cần tạo một đối tượng mới từ một đối tượng đã có
(chỉ với các lớp do người sử dụng định nghĩa còn với những kiểu dữ liệu cơ sở như int,
float... thì không). Hàm khởi tạo sao chép có khai báo như sau X(X&) trong đó X là tên
lớp. Tham số truyền vào là tham chiếu vì nếu truyền bằng tham trị thì bản thân hàm khởi
tạo sao chép cũng cần tạo đối tượng mới từ đối tượng đã có và nó sẽ phải gọi chính nó...
Hàm khởi tạo sao chép mặc định sẽ tự động được tạo ra nếu có yêu cầu đến nó và hàm
khởi tạo sao chép của lớp tương ứng chưa được định nghĩa. Nếu một lớp chứa đối tượng
của lớp khác. Hàm khởi tạo mặc định của lớp chứa sẽ gọi hàm khởi tạo của lớp bị chứa
(hàm này sẽ lại được tạo ra nếu chưa được định nghĩa)...

Khi một hàm được gọi, chương trình dịch sẽ cất các tham số của hàm đó vào stack (nếu
là cấu trúc lớp do người sử dụng định nghĩa thì việc copy được thực hiện bằng hàm tạo
sao chép của lớp đó), sau đó là địa chỉ trả về của hàm, sau đó cách một khoảng vàấu đó
lưu trữ các biến cục bộ của hàm. Với giá trị trả về có kiểu lớp do người sử dụng định
nghĩa, có một giá trị tự động đựơc thêm vào danh sách tham số đó là địa chỉ của biến
nhận giá trị trả về của hàm. Trước khi trở, hàm sẽ copy nội dung trả về vào vùng nhớ xác
định bởi địa chỉ đó sử dụng hàm tạo sao chép của đối tượng. (Với các kiểu cơ sở giá trị
trả về sẽ đựơc lưu trong thanh ghi).

Chương 14 : Kế thừa và kết tập :


Mục đích của việc sử dụng kế thừa và kết tập là sử dụng lại mã nguồn. Kế thừa và kết tập
có rất nhiều đặc điểm giống nhau.
Khi kế thừa một lớp A từ lớp B và tạo một đối tượng của lớp A, một đối tượng của lớp B
sẽ được tạo và tồn tại như một thành phần trong đối tượng của A (các thành phần private
của đối tượng lớp B cũng tồn tại nhưng ta không truy xuất được).
Ngoài ra hàm tạo của lớp B sẽ tự động được gọi trước hàm tạo của lớp A, sau đó là hàm
tạo của các đối tượng thuộc lớp A theo thứ tự khai báo từ trên xuống rồi mới đến hàm tạo
của lớp A. Hàm huỷ thì đúng theo thứ tự ngược lại.
Khi ta định nghĩa lại hàm của lớp cha thì sẽ không sử dụng được các hàm chồng của hàm
đó ở lớp cha, nếu ta định nghĩa một hàm cùng tên nhưng khác tham số hoặc giá trị trả về
ở lớp con thì tất cả các hàm cùng tên của lớp cha cũng không sử dụng được nữa (các vấn
đề với chồng hàm trong lớp cha).
Các hàm không được kế thừa từ lớp cha sang lớp con là hàm tạo, hàm huỷ và toán tử gán.
Tuy tương đối giống nhau nhưng kết tập thường được sử dụng nếu ta muốn gộp nhiều đối
tượng thành một đối tượng mới hoặc muốn sử dụng tính năng của đối tượng có sẵn trong
khi giao diện là giao diện do chúng ta thiết kế; kế thừa được sử dụng khi ta muốn sử dụng
lại đối tượng ở mức độ thiết kế, chủ yếu là để cung cấp một giao diện gần giống với giao
diện của một lớp sẵn có.
Khi một lớp A kế thừa từ lớp B, mọi tham số kiểu tham chiếu hoặc con trỏ truyền vào có
kiểu là B đều có thể được thay thế bằng A (nếu thay tham số đối tượng có thể sẽ có vấn
đề xẩy ra), khi đó hàm của lớp B sẽ được gọi (kể cả khi đã định nghĩa lại trong lớp A
(khai báo hàm trong lớp B không có từ khoá virual)). VD : void f(B& b); A a; f(a);
Chú ý : Trong mọi trường hợp nếu hàm tạo của một đối tượng không được gọi mà nó cần
được gọi, hàm tạo mặc định của đối tượng đó sẽ được gọi. Vì thế hàm tạo sao chép mặc
định của một đối tượng sẽ gọi hàm tạo sao chép của lớp cha và các đối tượng thành viên
nhưng nếu ta viết đè hàm tạo sao chép của đối tượng và không gọi các hàm tạo khác thì
hàm tạo mặc định của lớp cha và các đối tượng thành viên sẽ đựơc gọi thay vì hàm tạo
sao chép.

You might also like