Bài giảng Ngôn ngữ lập trình C và C+ - Bài 6: Cấu trúc và Lớp - Đỗ Đăng Khoa
Một tập hợp của một hoặc nhiều biến, có thể khác kiểu nhau,
được nhóm lại dưới một tên duy nhất cho tiện xử lý
Trong các ứng dụng về cơ sở dữ liệu, kiểu cấu trúc còn được
gọi là bản ghi
Việc định nghĩa cấu trúc sẽ tạo ra kiểu dữ liệu mới
Ví dụ:
Hồ sơ nhân viên: mỗi nhân viên được mô tả bởi một tập các
thuộc tính như: tên, địa chỉ, số CMT, lươngM. Một trong số các
thuộc tính này lại có thể là một cấu trúc: tên có thể có vài thành
phần (họ, tên đệm, tên), địa chỉ và lương cũng có thể như vậy
Tài khoản ngân hàng: tên chủ tài khoản, tên tài khoản, số dư
tài khoản, loại tiề
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Ngôn ngữ lập trình C và C+ - Bài 6: Cấu trúc và Lớp - Đỗ Đăng Khoa", để tải tài liệu gốc về máy hãy click vào nút Download ở trên
Tóm tắt nội dung tài liệu: Bài giảng Ngôn ngữ lập trình C và C+ - Bài 6: Cấu trúc và Lớp - Đỗ Đăng Khoa
5/12/2015 1 TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Ngôn ngữ lập trình C và C++ Bài 6: Cấu trúc và Lớp TS. Đỗ Đăng Khoa Bộ môn Cơ học Ứng dụng Viện Cơ khí 5/12/2015 2 Khái niệm về Cấu trúc (Struct) Một tập hợp của một hoặc nhiều biến, có thể khác kiểu nhau, được nhóm lại dưới một tên duy nhất cho tiện xử lý Trong các ứng dụng về cơ sở dữ liệu, kiểu cấu trúc còn được gọi là bản ghi Việc định nghĩa cấu trúc sẽ tạo ra kiểu dữ liệu mới Ví dụ: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Hồ sơ nhân viên: mỗi nhân viên được mô tả bởi một tập các thuộc tính như: tên, địa chỉ, số CMT, lươngM. Một trong số các thuộc tính này lại có thể là một cấu trúc: tên có thể có vài thành phần (họ, tên đệm, tên), địa chỉ và lương cũng có thể như vậy Tài khoản ngân hàng: tên chủ tài khoản, tên tài khoản, số dư tài khoản, loại tiền 5/12/2015 3 Khai báo cấu trúc Khai báo một cấu trúc struct { các thành phần ; } ; Ví dụ: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI struct point { int x; int y; }a,b,c; 5/12/2015 4 Khai báo cấu trúc Mỗi thành phần giống như một biến riêng của kiểu, nó gồm kiểu và tên thành phần. Một thành phần cũng còn được gọi là trường. Phần tên của kiểu cấu trúc và phần danh sách biến cấu trúc có thể có hoặc không. Tuy nhiên trong khai báo kí tự kết thúc cuối cùng phải là dấu chấm phẩy (;). TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Các kiểu cấu trúc được phép khai báo lồng nhau, nghĩa là một thành phần của kiểu cấu trúc có thể lại là một trường có kiểu cấu trúc. Một biến có kiểu cấu trúc sẽ được phân bố bộ nhớ sao cho các thực hiện của nó được sắp liên tục theo thứ tự xuất hiện trong khai báo. 5/12/2015 5 Khai báo biến kiểu cấu trúc Khai báo ngay sau dấu ngoặc }, danh sách các biến; struct { ... } x, y, z; Khai báo như biến thông thường (trong C) struct TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Khai báo như biến thông thường (trong C++) ; 5/12/2015 6 Khởi tạo biến cấu trúc Khởi tạo ngay định nghĩa của nó với danh sách các khởi tạo cho các thành phần point pt = {10, 20}; Sử dụng toán tử gán point pt1 = {10, 20}, pt2; pt2 = pt1; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Ví dụ: struct rect { point p1,p2; }; rect rect1={{1,2},{3,4}}; 5/12/2015 7 Truy cập đến thành phần của cấu trúc Biến không phải con trỏ tên_cấu_ trúc.thành_phần Biến con trỏ: tên_cấu_ trúc->thành_phần, (*tên_cấu_trúc).thành_phần Ví dụ: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI In tọa độ điểm pt: printf("%d,%d", pt.x, pt.y); //Tính khoảng cách từ pt đến tọa độ: Double dist = sqrt((double)pt.x * pt.x + (double)pt.y * pt.y); 5/12/2015 8 Cấu trúc lồng nhau Hình chữ nhật là một cặp điểm xác định hai góc đối diện. struct rect { point pt1; point pt2; }; Nếu khai báo screen là TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI rect screen; thì screen.pt1.x chỉ đến tọa độ x của thành phần pt1 của screen. 5/12/2015 9 Hàm và Cấu trúc Các thao tác hợp lệ duy nhất với một cấu trúc là Sao chép nó hoặc gán cho nó, Lấy địa chỉ qua &, Truy xuất các thành phần của nó. Việc sao chép và gán bao gồm TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Truyền đối số tới hàm Trả giá trị từ hàm 5/12/2015 10 Hàm và Cấu trúc Hàm trả về một cấu trúc là một biến cấu trúc. là một con trỏ cấu trúc. là một tham chiếu cấu trúc. Ví dụ hàm trả về biến cấu trúc struct Sophuc// Khai báo kiểu số phức dùng chung TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI { float thuc; float ao; }; 5/12/2015 11 Hàm và Cấu trúc Sophuc Cong(Sophuc x, Sophuc y) { Sophuc kq; kq.thuc = x.thuc + y.thuc ; kq.ao = x.ao + y.ao ; return kq; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI } void In(Sophuc x) { cout << "(" << x.thuc << "," << x.ao << ")" << endl ; } 5/12/2015 12 Hàm và Cấu trúc void main(){ Sophuc x, y; cout > x.thuc >> x.ao ; cout > y.thuc >> y.ao ; cout << "x + y = " ; In(Cong(x,y)) ;} Ví dụ hàm trả về con trỏ cấu trúc TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Sophuc* Tru(Sophuc x, Sophuc y){ Sophuc* kq=new Sophuc; kq->thuc = x.thuc + y.thuc ; kq->ao = x.ao + y.ao ; return kq; } 5/12/2015 13 Hàm và Cấu trúc Hàm có đối số là cấu trúc Là một biến cấu trúc Là một con trỏ cấu trúc Là một tham chiếu cấu trúc Là một mảng cấu trúc hình thức hoặc con trỏ mảng TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Trường hợp cấu trúc lớn, sử dụng con trỏ và tham chiếu sẽ hiệu quả hơn việc phải sao chép cả cấu trúc. Con trỏ cấu trúc tương tương tự như con trỏ tới các biến thông thường. 5/12/2015 14 Bảng (Mảng) Cấu trúc Khai báo: struct_name {} tenbang[kích_thước]; struct_name tenbang[kích_thước]; Khởi tạo: M = {,,,} hoặc ..={{,,},{,,},M} Truy cập: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI tenbang[i] Ví dụ: //mảng mười biến kiểu point point a[10]; 5/12/2015 15 Con trỏ Cấu trúc Khai báo: struct_name * ten_con_tro; Khởi gán thông qua phép lấy địa chỉ & Ví dụ: point p1={1,2}, *p2; p2=&p1; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Cấp phát động và thu hồi bộ nhớ cũng thông qua: new và delete Ví dụ: point *p1=new point; delete p1; int n=10; point *p2=new point[n]; delete []p2; 5/12/2015 16 Kiểu Hợp Kiểu hợp cũng có nhiều thành phần giống kiểu cấu trúc Tuy nhiên, các thành phần của chúng sử dụng chung nhau một vùng nhớ Kích thước của một kiểu hợp là độ dài của trường lớn nhất và việc Thay đổi giá trị một thành phần sẽ ảnh hưởng đến tất cả các TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI thành phần còn lại Ví dụ: union { Danh sách các thành phần; }; 5/12/2015 17 Truy cập đến thành phần của hợp Biến không phải con trỏ tên_cấu_ trúc.thành_phần Biến con trỏ: tên_cấu_ trúc->thành_phần, (*tên_cấu_trúc).thành_phần Ví dụ: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI union foo { int x; int y; }; foo f; f.x = 10; /* cũng mang giá trị 10 vì dùng chung bộ nhớ với f.x */ printf("%d\n", f.y); 5/12/2015 18 Từ Khóa typedef Một kiểu dữ liệu có thể được định nghĩa bằng cách sử dụng từ khóa typedef Nó không tạo ra một kiểu dữ liệu mới, mà định nghĩa một tên mới cho một kiểu đã có. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Cú pháp: typedef type tên; Ví dụ: typedef float deci; 5/12/2015 19 Lập trình hướng đối tượng Đối tượng: là một đơn vị đầy đủ được kết hợp bởi các dữ liệu và chỉ thị Đối tượng được chia thành hai thành phần: các phương thức (hàm) và các thuộc tính (biến) Phương thức: là phương tiện để sử dụng đối tượng, TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI trong khi các thuộc tính sẽ mô tả đối tượng có tính chất gì Đối tượng được trừu tượng hóa qua việc định nghĩa của các lớp 5/12/2015 20 Các đặc tính của lập trình hướng đối tượng Tính trừu tượng (abstraction): Bỏ qua một số khía cạnh thông tin, chỉ tập trung vào những cốt lõi cần thiết Mỗi đối tượng có thể hoàn tất các công việc một cách nội bộ, báo cáo, thay đổi trạng thái của nó và liên lạc với các đối tượng khác, không cần cho biết làm cách nào tiến hành TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI được các thao tác (trừu tượng dự liệu) Tính trừu tượng còn thể hiện qua việc một đối tượng ban đầu có thể có một số đặc điểm chung cho nhiều đối tượng khác như là sự mở rộng của nó nhưng bản thân đối tượng này có thể không có các biện pháp thi hành (lớp trừu tượng hay lớp cơ sở) 5/12/2015 21 Các đặc tính của lập trình hướng đối tượng Tính đóng gói (encapsulation) và che giấu thông tin (information hiding): Tính chất này không cho phép người sử dụng các đối tượng thay đổi trạng thái nội tại của một đối tượng Chỉ có các phương thức nội tại của đối tượng cho phép thay đổi trạng thái của nó TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Tính đa hình (polymorphism): Thông qua việc gửi các thông điệp (message) Các phương thức dùng trả lời cho một thông điệp sẽ tùy theo đối tượng mà thông điệp đó được gửi tới sẽ có phản ứng khác nhau 5/12/2015 22 Các đặc tính của lập trình hướng đối tượng Tính kế thừa (inheritance): Cho phép một đối tượng có thể có sẵn các đặc tính mà đối tượng khác đã có thông qua kế thừa Cho phép các đối tượng chia sẻ hay mở rộng các đặc tính sẵn có mà không phải tiến hành định nghĩa lại TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Không phải ngôn ngữ hướng đối tượng nào cũng có tính chất này. 5/12/2015 23 Khái niệm về lớp (Class) Một lớp bao gồm các hàm và dữ liệu có liên quan Các hàm này là các hàm thành phần (member function) hay còn là phương thức (method) TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Giống như cấu trúc, lớp có thể xem như một kiểu dữ liệu Từ một lớp có thể tạo ra (bằng cách khai báo) nhiều đối tượng (biến, mảng) khác nhau. Mỗi đối tượng có vùng nhớ riêng của mình 5/12/2015 24 Khai báo lớp (Class) Cú pháp: class tên_lớp { ñặc_tả_truy_cập_1: member1; ñặc_tả_truy_cập_2: member2; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI ... }danh_sách_ñối_tượng; Ví dụ: class CRectangle { int x, y; public: int area (void);} rect; 5/12/2015 25 Khai báo lớp (Class) Việc khai báo một lớp không chiếm giữ bộ nhớ, chỉ các đối tượng của lớp mới thực sự chiếm giữ bộ nhớ. Thuộc tính của lớp có thể là các biến, mảng, con trỏ có kiểu chuẩn (int, float, char, char*, long,...) TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Thuộc tính của lớp có thể là kiểu ngoài chuẩn đã định nghĩa trước (struct, union, class,...) Thuộc tính của lớp không thể có kiểu của chính lớp đó, nhưng có thể là con trỏ của lớp này 5/12/2015 26 Khai báo lớp (Class)- Các đặc tả truy cập Các đặc tả truy cập này thay đổi các quyền truy cập mà các thành phần khai báo sau chúng có được: private: chỉ có thể truy cập từ bên trong thành phần cùng lớp đó (trong thân các phương thức của lớp) hoặc từ các thành phần bạn (friend) của nó. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI protected: như private, ngoài ra còn từ các thành phần của các lớp dẫn xuất (lớp con) của lớp đó. public: có thể truy cập từ mọi nơi mà đối tượng hiển thị. Mặc định của class là quyền truy cập private đối với tất cả thành phần của nó 5/12/2015 27 Khai báo lớp (Class)- Các đặc tả truy cập Nếu các thành phần dữ liệu đã khai báo là private thì các hàm thành phần phải có ít nhất một vài hàm được khai báo dạng public để có thể truy cập được, nếu không toàn bộ lớp sẽ bị đóng kín và điều này không giúp gì cho chương trình TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Cách khai báo lớp tương đối phổ biến là các thành phần dữ liệu được ở dạng private và hàm thành phần dưới dạng public 5/12/2015 28 Khai báo lớp (Class)- Dữ liệu thành phần Khai báo như khai báo các thành phần trong kiểu cấu trúc hay hợp Bình thường được khai báo là private để bảo đảm tính giấu kín, bảo vệ an toàn dữ liệu của lớp không cho phép TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI các hàm bên ngoài xâm nhập vào các dữ liệu này. Không được khai báo là auto, register hoặc extern Kiểu: enum, kiểu dữ liệu có sẵn (chuẩn) hoặc người dùng định nghĩa (struct, union, class) 5/12/2015 29 Khai báo lớp (Class)- Hàm thành phần Hàm thành phần dùng để truy cập có kiểm soát vào thành phần dữ liệu của lớp Thường khai báo là public để chúng có thể được gọi tới (sử dụng) từ các hàm khác trong chương trình TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Hàm khai báo là private chỉ có thể được gọi bởi các hàm public khác trong lớp Bản mẫu hàm: được khai báo bên trong phần thân lớp. 5/12/2015 30 Định nghĩa lớp (Class)- Hàm thành phần Định nghĩa hàm: có thể được triển khai luôn trong thân lớp hoặc bên ngoài lớp cùng toán tử phạm vi :: (kiểu_trả_về tên_lớp::tên_hàm()) TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Hàm được định nghĩa bên trong lớp sẽ được tự động coi là hàm thành phần inline bởi trình biên dịch Hàm thành phần được phép truy xuất tới các dữ liệu thành phần, kể cả dữ liệu kiểu private 5/12/2015 31 Định nghĩa lớp (Class)- Hàm thành phần Ví dụ: #include #include class point{ private: int x, y, m ; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI public: void inputdata() ; void displaypoint() ; //Hiện một ñiểm //Ẩn một ñiểm, hàm ñịnh nghĩa trong khai báo void hidepoint() { putpixel(x, y,getbkcolor()); } }; 5/12/2015 32 Định nghĩa lớp (Class)- Hàm thành phần void point::inputdata(){ cout <<"\n Nhap hoanh do va tung do cua diem:”; cin >> x >> y ; cout << “\n Nhap ma mau cua diem: “; cin >> m ; } TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI void point::displaypoint(){ int mau_ht ; mau_ht = getcolor(); putpixel(x, y, m); setcolor(mau_ht); } 5/12/2015 33 Phạm vi lớp Ngoài hai phạm vi toàn cục và cục bộ, C++ đưa ra khái niệm về phạm vi lớp Mọi thành phần của lớp được gọi là trong phạm vi của lớp đó Mọi thành phần của lớp đều có thể tham khảo tới bất kì thành phần nào khác của cùng lớp TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Các hàm thành phần của lớp có quyền truy cập không hạn chế vào thành phần dữ liệu của lớp đó Việc truy cập vào các thành phần dữ liệu và hàm từ ngoài phạm vi lớp do người lập trình kiểm soát 5/12/2015 34 Đối tượng, Mảng và con trỏ đối tượng của lớp Một đối tượng (object) là một thể nghiệm của lớp Lớp là một định nghĩa của đối tượng. Chú ý: Lớp là một kiểu dữ liệu, đối tượng của lớp này chỉ là một biến. Ví dụ: point a; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Cách khai báo mảng đối tượng, con trỏ đối tượng cũng giống như khai báo biến, mảng các kiểu khác (như int, float, struct, union,...) Ví dụ: point b[10], *c; c= new point; 5/12/2015 35 Truy xuất thuộc tính của đối tượng Mỗi thuộc tính đều thuộc về một đối tượng, không thể viết tên thuộc tính một cách riêng rẽ mà bao giờ cũng phải có tên đối tượng đi kèm Truy xuất thuộc tính của đối tượng bằng toán tử chấm . tên_đối_tượng.Tên_thuộc_tính con_trỏ_đối_tượng->Tên_thuộc_tính TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Ví dụ: point a,*b; a.x;// chỉ dùng ñược trong hàm thành phần b=&a; b->y; // chỉ dùng ñược trong hàm thành phần Chỉ có thể truy xuất thuộc tính private của đối tượng bằng các hàm thành phần 5/12/2015 36 Sử dụng hàm thành phần của đối tượng Cũng giống như hàm thông thường, hàm thành phần được sử dụng thông qua lời gọi. Tuy nhiên trong lời gọi hàm thành phần bao giờ cũng phải có tên đối tượng để chỉ rõ hàm thực hiện trên các thuộc tính của đối tượng nào. Ví dụ: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI void main(){ point a; a.inputdata(); } 5/12/2015 37 Đối của hàm thành phần, con trỏ this Con trỏ this là con trỏ tới chính đối tượng của nó Con trỏ this là đối thứ nhất của hàm thành phần Các thuộc tính viết trong hàm inputdata() gọi bởi một đối tượng được hiểu là thuộc chính đối tượng đó do con trỏ this trỏ tới Cách viết tường minh lại hàm inputdata() TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI void point::inputdata(){ cout <<"\n Nhap hoanh do va tung do cua diem:”; cin >> this->x >>this-> y ; cout << “\n Nhap ma mau cua diem: “; cin >> this->m ; } 5/12/2015 38 Đối của hàm thành phần, con trỏ this Tham số truyền cho đối con trỏ this chính là địa chỉ của đối tượng đi kèm với phương thức trong lời gọi phương thức Ví dụ: point a; a.inputdata() Trong trường hợp này tham số truyền cho con trỏ this chính TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI là địa chỉ của a: this = &a Con trỏ this còn được dùng trong các hàm thành phần cần trả lại chính đối tượng có phương thức đang triển khai. 5/12/2015 39 Đối tượng hằng và các hàm thành phần hằng Đối tượng hằng là đối tượng được khai báo với từ khoá cons Mọi ý định sửa đổi các đối tượng hằng đều bị chương trình báo lỗi khi biên dịch Các hàm thành phần "không sủa đổi dữ liệu của lớp", tức là các hàm thành phần hằng và là các hàm được khai báo với từ khoá const, mới được phép thực hiện trên các đối tượng hằng TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Khi viết các hàm thành phần của lớp, cần xác định ngay hàm nào cần sửa hàm nào không cần sửa đổi dữ liệu của lớp và đặt thêm từ khoá const tương ứng trong khai báo và định nghĩa hàm. 5/12/2015 40 Đối tượng hằng và các hàm thành phần hằng Ví dụ: class Matrix{ int row,col; double data[100][100]; public: void Transpose(); TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI double Det() const; // hàm thành phần hằng }; int main(){ Matrix const m; m.Transpose(); // error // OK vì Det() là hàm thành phần hằng double d = m.Det(); } 5/12/2015 41 Định nghĩa lớp- Hàm dựng (tạo)/ Cấu tử Các đối tượng cần được khởi tạo dữ liệu thành phần hoặc gán bộ nhớ động trong quá trình sinh ra để tránh việc trả lại các giá trị không mong muốn trong quá trình thao tác chúng Hàm dựng cũng là một hàm thành phần của lớp (nhưng là hàm đặc biệt) được tự động gọi bất cứ khi nào một đối tượng mới của lớp này được tạo ra TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Chương trình dịch sẽ cấp phát bộ nhớ cho đối tượng sau đó sẽ gọi đến hàm dựng Hàm dựng sẽ khởi gán giá trị cho các thuộc tính của đối tượng và có thể thực hiện một số công việc khác nhằm chuẩn bị cho đối tượng mới. 5/12/2015 42 Định nghĩa lớp- Hàm dựng (tạo)/ Cấu tử Hàm dựng phải có tên giống tên lớp, không có giá trị trả về (kể cả void). Nếu không định nghĩa hàm dựng của một lớp, trình biên dịch sẽ sinh ra hàm dựng ngầm định. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Hàm dựng ngầm định không có đối và chỉ đơn thuần đặt không vào mọi byte của biến thể nghiệm của một đối tượng Một lớp có thể có nhiều hơn một hàm dựng (cùng tên, khác bộ đối số) 5/12/2015 43 Định nghĩa lớp- Hàm dựng (tạo)/ Cấu tử class point { private: int x,y,m; public: point()// hàm dựng không ñối TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI {x=0; y=0; m=1;} //hàm dựng có ñối point(int x1, int y1, int m1); }; 5/12/2015 44 Định nghĩa lớp- Hàm dựng (tạo)/ Cấu tử point :: point(int x1, int y1, int m1) {x = x1; y = y1; m = m1; } Ví dụ: point a; // Gọi tới hàm dựng không ñối. // Kết quả a.x = 0, a.y = 0, a.m = 1 point b(300, 100, 5);// Gọi tới hàm dựng có ñối. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI // Kết quả b.x = 300, b.y = 100, b.m = 5 point c[5] ;// Gọi tới hàm dựng không ñối 5 lần Các hàm có đối kiểu lớp, thì đối chỉ xem là các tham số hình thức, vì vậy khai báo đối (trong dòng đầu của hàm) sẽ không tạo ra đối tượng mới và do đó không gọi tới các hàm dựng 5/12/2015 45 Định nghĩa lớp- Hàm dựng sao chép Một hàm dựng tạo ra đối tượng mới từ đối tượng đã có được gọi là hàm dựng sao chép. Hàm dựng sao chép chỉ có một đối: tham khảo tới một đối tượng thuộc cùng lớp Ví dụ: point::point(const point& source) TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI { x= source.x; y= source.y; m= source.m; } 5/12/2015 46 Định nghĩa lớp- Hàm dựng sao chép Nếu không được định nghĩa, trình biên dịch sẽ tạo ra cấu tử sao chép ngầm định. Cấu tử này sao đối tượng nguồn theo từng bit sang đối tượng mới. Hàm dựng sao chép trong ví dụ trên không khác gì hàm dựng sao chép mặc định. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Khi lớp có các thuộc tính con trỏ hoặc tham chiếu, thì hàm dựng sao chép mặc định chưa đáp ứng được yêu cầu (ví dụ sao chép mặc định hai con trỏ của 2 đối tượng thì hai đối tượng dùng chung bộ nhớ con trỏ-> hai đối tượng không độc lập). 5/12/2015 47 Định nghĩa lớp- Toán tử gán = Nếu không định nghĩa toán tử này, trình biên dịch sẽ sinh ra toán tử gán mặc định. Toán tử mặc định này sẽ sao chép từng bit từ nơi nguồn sang nơi nhận. Hàm dựng sao chép tạo ra đối tượng mới trong khi toán tử gán chỉ thay đổi giá trị của đối tượng hiện có. TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI point& point::operator=(const point& source){ if (this != &source) { x= source.x; y = source.y; m=source.m; } } 5/12/2015 48 Định nghĩa lớp- Hàm hủy/ Hủy tử Hàm hủy thực hiện chức năng ngược lại với hàm dựng Tự động gọi khi đối tượng bị hủy, hoặc do kết thúc phạm vi tồn tại của nó hoặc do được cấp phát động và được giải phóng bằng delete Hủy tử phải có tên giống tên lớp, nhưng có thêm dấu ~ phía trước, không có đối số và không có kiểu trả về (kể cả void). TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI point ::~ point() { } Nếu không định nghĩa hàm hủy, thì một hàm hủy mặc định không làm gì cả được phát sinh. Đối với nhiều lớp thì hàm hủy mặc định là đủ, và không cần đưa vào một hàm hủy mới 5/12/2015 49 Các lớp được định nghĩa với struct và union Các lớp có thể định nghĩa bằng các từ khóa struct và union. Chỉ có một sự khác nhau là các thành phần của lớp được khai báo với struct và union có quyền truy cập mặc định là public. Với union, nó chỉ chứa một thành phần dữ liệu tại một thời TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI điểm. 5/12/2015 50 Quá tải/ Nạp chồng/ Định nghĩa lại các toán tử Cú pháp: type operator sign (parameters) { /*...*/ } Ví dụ: point operator=(point a); point operator + (point a); point operator - (point a); TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI 5/12/2015 51 Quá tải/ Nạp chồng/ Định nghĩa lại các toán tử Khi nạp chồng toán tử cần chú ý xem toán tử là một ngôi (unary) hay hai ngôi (binary). Toán tử một ngôi thì danh sách rỗng Toán tử hai ngôi thì danh sách có một tham số Toán tử () có thể có số tham số tuỳ ý Những toán tử sau không thể nạp chồng TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI 5/12/2015 52 Một số điểm lưu ý về lớp Hàm dựng và hàm hủy đặc biệt quan trọng với những lớp có thành phần dữ liệu con trỏ sử dụng cấp phát bộ nhớ động và mảng bởi đây là các thành phần không được khởi tạo, sao chép hay giải toả tự động đúng. Để chúng có thể hoạt động được, tối thiểu phải triển TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI khai: Hàm dựng mặc định Hàm dựng sao chép Hàm hủy Ngoài ra để dễ sử dụng, nên triển khai toán tử gán (operator = ()). 5/12/2015 53 Ví dụ về lớp véc tơ class Vector { private: double * m_pData; int m_nSize; public: TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Vector(); Vector(int n); Vector(const double& val, int n); Vector& operator=(const Vector& va); ~Vector(); 5/12/2015 54 Ví dụ về lớp véc tơ double& operator[](int n); Vector operator+(const Vector& x); Vector operator-(const double& x); }; Vector::Vector() TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI { m_nSize = 0; m_pData = 0; // Giong nhu m_pData = NULL; } 5/12/2015 55 Ví dụ về lớp véc tơ Vector::Vector(int n){ m_nSize = n; m_pData = new double[m_nSize]; for (int i = 0; i < m_nSize; i++) m_pData[i] = 0.0; } TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Vector::Vector(const double& val, int n){ m_nSize = n; m_pData = new double[m_nSize]; for (int i = 0; i < m_nSize; i++) m_pData[i] = val; } 5/12/2015 56 Ví dụ về lớp véc tơ Vector::~Vector(){ delete [] m_pData; // Chú ý dẫu [] } Vector& Vector::operator=(const Vector& va) { delete [] m_pData; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI this->m_nSize = va.m_nSize; this->m_pData = new double [m_nSize]; for (int i = 0; i < m_nSize; i++) this->m_pData[i] = va.m_pData[i]; return *this; } 5/12/2015 57 Ví dụ về lớp véc tơ double& Vector::operator[](int i) { return m_pData[i]; } Vector Vector::operator+(const Vector& x) { TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI Vector t(this->m_nSize); for (int i = 0; i < m_nSize; i++) t.m_pData[i] = this->m_pData[i]+x.m_pData[i]; return t; } 5/12/2015 58 Ví dụ về lớp véc tơ Vector Vector::operator-(const double& x){ Vector t(this->m_nSize); for (int i = 0; i < m_nSize; i++) t.m_pData[i] = this->m_pData[i]-x; return t; } TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI int main(){ Vector v; // Constructor mặc ñịnh ñược gọi // Constructor với 2 tham số ñược gọi Vector u(1.0, 2); Vector x(u); // Constructor sao chép (copy) v=x+u;// toán tử cộng và gán ñược gọi } 5/12/2015 59 Thành phần tĩnh (static) Một lớp có thể chứa các thành phần tĩnh, hoặc dữ liệu hoặc hàm Thành phần dữ liệu tĩnh: chỉ có một giá trị duy nhất cho mọi đối tượng của lớp đó và tồn tại ngay cả khi không có đối tượng nào của lớp đó. Hàm thành phần tĩnh: dùng để truy xuất các biến tĩnh được TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI xác định là private Hàm thành phần tĩnh không gắn với một đối tượng nào cụ thể của lớp, có thể gọi trực tiếp bằng tên lớp với toán tử :: 5/12/2015 60 Thành phần tĩnh (static) #include using namespace std; class CDummy { private: static int m; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI public: static int n; CDummy () { n++; m++ }; ~CDummy () { n--; m--}; static int getnumcount(){return m;} }; 5/12/2015 61 Thành phần tĩnh (static) int CDummy::n=0; int CDummy::m=0; int main () { CDummy a; CDummy b[5]; TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI CDummy * c = new CDummy; cout << a.n << endl; //Gọi a.m là sai, gọi Cdummy::getnumcount(); delete c; cout << CDummy::n << endl; return 0;} 5/12/2015 62 Hàm bạn hữu (friend) Ngoài quy tắc trao quyền truy cập thông qua các từ khoá truy cập, C++ còn cho phép trao quyền truy cập các thành phần của một lớp cho một số hàm hay lớp khác, tạo thuận lợi cho việc triển khai và sử dụng chúng. Các hàm bạn là các hàm không phải là thành phần của lớp, được khai báo với từ khoá friend và có quyền truy cập đến cả TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI các thành phần private và protected của lớp. Một lớp bạn B của lớp A là lớp có tên được liệt kê trong phần khai báo của lớp A với từ khoá friend và các hàm thành phần của B có quyền truy cập đến các thành phần private và protected của lớp A. 5/12/2015 63 Hàm bạn hữu (friend) class Matrix{ public: Matrix AddTo(Matrix const & m); friend Matrix Add(Matrix const & m1, Matrix const & m2); friend Matrix operator + (Matrix const & m1, Matrix TRƯỜNG ĐẠI HỌC BÁCH KHOA HÀ NỘI const & m2); }; Matrix m1, m2, m3, m4; m3 = m1.AddTo(m2); // gọi hàm thành phần Addto() m4 = Add(m1, m2); // Gọi hàm bạn hữu Add() m4 = m1 + m2; // Gọi hàm bạn hữu là toán tử cộng
File đính kèm:
- bai_giang_ngon_ngu_lap_trinh_c_va_c_bai_6_cau_truc_va_lop_do.pdf