Bài giảng Cơ sở dữ liệu - Chương 1: Lớp và đối tượng

ppt 125 trang hapham 2800
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Cơ sở dữ liệu - Chương 1: Lớp và đối tượng", để tải tài liệu gốc về máy bạn click vào nút DOWNLOAD ở trên

Tài liệu đính kèm:

  • pptbai_giang_co_so_du_lieu_chuong_1_lop_va_doi_tuong.ppt

Nội dung text: Bài giảng Cơ sở dữ liệu - Chương 1: Lớp và đối tượng

  1. 1 Chương 1 LỚP VÀ ĐỐI TƯỢNG
  2. 2 Những nội dung chính Kiểu dữ liệu trừu tượng (Abstract data type) Lớp Đối tượng Ngôn ngữ UML Các ví dụ Các phương thức tạo/hủy đối tượng Con trỏ this
  3. 3 Tài liệu đọc
  4. 4 Tài liệu đọc (tt)
  5. 5 Tài liệu đọc (tt)
  6. 6 Kiểu dữ liệu trừu tượng Nhớ lại các đặc trưng cơ bản của LTHĐT Sự trừu tượng Đóng bao – Che giấu thông tin Thừa kế Đa hình Trừu tượng Quan tâm đến các đặc điểm chính bỏ qua các chi tiết không cần thiết Trừu tượng hóa dữ liệu Quan tâm đến các tác vụ (hành vi) trên dữ liệu mà bỏ qua các cài đặc các tác vụ Kiểu dữ liệu trừu tượng Sự trừu tượng mức cao (quản lý độ phức tạp thông qua trừu tượng) Đóng bao giữa dữ liệu và các hành vi Che giấu thông tin
  7. 7 Sự trừu tượng và đóng bao
  8. 8 Kiểu dữ liệu trừu tượng Là một kiểu dữ liệu đặc tả các tính chất logic (các giá trị có thể và các tác vụ trên đó) bỏ qua các cài đặt bên trong LOGICAL PROPERTIES IMPLEMENTATION What are the possible values? How can this be done in C++/Java? What operations will be needed? How can data types be used?
  9. 9 Kiểu dữ liệu trừu tượng (tt)
  10. 10 Mô hình ADT Abstract Data Type Abstract Data Structure Interface Operations
  11. 11 Kiểu dữ liệu trừu tượng có sẵn TYPE int Value range: Representation of INT_MIN . . INT_MAX int Operations: + prefix as 16 bits two’s - prefix (inside) complement + infix - infix + * infix / infix Implementation of % infix Operations Relational Operators infix
  12. 12 Lớp Là kiểu dữ liệu trừu tượng do người lập trình định nghĩa Là một khung mẫu cho các đối tượng Được xác định (tìm) từ các “danh từ” trong một lĩnh vực của bài toán Các thuộc tính (dữ liệu) là các “danh từ” có liên quan đến “các danh từ của lớp” Các hành vi (phương thức) thường là các động từ
  13. 13 Lớp (tt)
  14. 14 Các cơ chế tạo ra các lớp Xác định các thuộc tính Những gì mà ta biết về đối tượng – giống như một struct Xác định các phương thức Những gì mà đối tượng có thể làm Xác định các quyền truy xuất (sẽ trình bày sau) Việc xác định các thuộc tính của các lớp còn phụ thuộc vào việc sử dụng các đối tượng trong các bài toán/lĩnh vực khác nhau
  15. 15 Các lớp mô hình cho các đặc trưng cơ bản của các đối tượng thực Dog name colour Dog name owner disease
  16. Các lớp cũng mô hình các hành vi của các 16 đối tượng thực Dog Bird Alarm Name type alarmTime Colour sound alarmMode bark() sing() setAlarmTime() eat() setSound() stopAlarm() isAlarmSet()
  17. 17 Một ví dụ về lớp Thuộc tính (dữ liệu) •Lớp Hành vi (phương thức) Tên Khóa học Thêm một sinh viên Vị trí Xóa một sinh viên Ngày đăng ký Lấy danh sách sinh viên Số tín chỉ Kiểm tra ngày hết hạn Ngày bắt đầu Ngày kết thúc
  18. 18 Biểu diễn lớp theo UML UML (Unified Modeling Language) Là một kỹ thuật để mô hình hóa một cách trực quan các kết quả trong công nghệ phần mềm hướng đối tượng Trình bày các lược đồ cho LTHĐT Trong UML, một lớp được biểu diễn bằng một hình chữ nhật gồm có 3 phần: Lecturer
  19. 19 Các thành phần của lớp Phần thứ nhất: chứa tên lớp Phần thứ hai: chứa các thuộc tính/cấu trúc của lớp Phần thứ ba: chứa các hành vi/phương thức của lớp Lecturer Name empID create() change() save() delete()
  20. 20 Các thành phần của lớp (tt) Phần thứ hai và phần thứ ba có thể bỏ qua nếu thấy không cần thiết Lecturer Lecturer Lecturer Lecturer Name Name empID empID create() create() change() change() save() save() delete() delete() Lecturer
  21. 21 Các thành phần của lớp (tt) Các kí hiệu dùng để chỉ phạm vi truy cập các thành viên của lớp: + Public access # Protected access - Private access Class - privateAttribute # protectedAttribute +publicOp() # protectedOp() - privateOp()
  22. 22 Đối tượng Là một minh họa của một lớp Là một biến của một kiểu dữ liệu trừu tượng Bird type sound sing() setSound()
  23. 23 Một đối tượng có trạng thái Trạng thái của một đối tượng là một trong những điều kiện cần có để nó tồn tại Trạng thái của một đối tượng thường thay đổi theo thời gian Được biểu diễn bởi: Các giá trị thuộc tính và các liên kết giữa thuộc tính và giá trị Name Y.Welikala Employee ID 567138 Y.Welikala Date hired Oct 18, 2004 Status Teaching
  24. 24 Một đối tượng có hành vi Hành vi cho biết một đối tượng hành động và đáp ứng lại các yêu cầu của các đối tượng khác như thế nào Hành vi được biểu diễn bởi một tập các thông điệp nó có thể đáp ứng được Assign Y.Welikala (Returns: conformation) Registration System CS 201 Course
  25. 25 Một đối tượng có định danh Một đối tượng có một định danh duy nhất cho dù nó có cùng trạng thái với các đối tượng khác Y. Welikala Teaches “Y.Welikala” “Y.Welikala” OOP Teaches OOP Teaches OOP
  26. 26 Biểu diễn các đối tượng bằng UML Một đối tượng được biểu diễn bằng một hình chữ nhật có gạch dưới các tên : Lecturer Chỉ có tên lớp Y.Welikala Y.Welikala : Chỉ có tên đối tượng Lecturer Tên lớp và tên đối tượng
  27. 27Các mối quan hệ giữa các lớp Association (kết hợp) Aggregation (Thu nạp) Composition (Cấu thành) Dependency (Phụ thuộc) Generalization (Tổng quát hóa)
  28. 28 Mối quan hệ: Association Mô hình hóa một liên kết ngữ nghĩa giữa các lớp Association name Professor Works for University Class Association Role Names Professor University Employee Employer
  29. 29 Mối quan hệ: Aggregation Một dạng đặc biệt của association mô hình hóa mối quan hệ toàn thể - bộ phận giữa một thực thể và các bộ phận của nó Part Whole Train Carriage Aggregation
  30. 30 Mối quan hệ: Composition Một dạng của aggregation có tính sở hữu cao và cùng chu khỳ sống Các bộ phận không thể sống lâu hơn thực thể chứa nó Part Whole Exam Paper Aggregation
  31. 31Association: Bản số và chiều Bản số xác định số đối tượng tham gia vào mối quan hệ Số các thể hiện của một lớp quan hệ với MỘT thể hiện của một lớp khác Được chỉ ra ở mỗi đầu của quan hệ association Association và aggregation mặc định là 2 chiều, nhưng người ta thường gới hạn theo một chiều Mũi tên thêm vào để chỉ chiều của mối quan hệ
  32. 32 Association: Bản số Không xác định Chỉ một 1 Không hoặc nhiều 0 * * Một hoặc nhiều 1 * Không hoặc một 0 1 Khoảng được chỉ định 2 4 Các khoảng không liên tục 2,4 6
  33. 33 Ví dụ: Bản số và chiều Bản số Student 1 0 * Schedule Chiều
  34. 34 Mối quan hệ: Dependency Quan hệ giữa 2 phần tử trong mô hình mà thay đổi ở phần tử này có thể gây ra thay đổi ở phần tử kia Quan hệ “sử dụng”, không cấu trúc Client Supplier Class Quan hệ Dependency
  35. 35 Mối quan hệ: Generalization Quan hệ giữa các lớp trong đó một lớp chia sẻ cấu trúc và/hoặc hành vi của một hoặc nhiều lớp khác Xác định một sự phân cấp các mức độ trừu tượng trong đó một lớp con có thể kế thừa một hoặc nhiều lớp cha Đơn thừa kế (Single inheritance) Đa thừa kế (Multiple inheritance) Generalization là quan hệ “là một dạng của”
  36. 36 Ví dụ: Đơn thừa kế Một lớp kế thừa từ một lớp khác Tổ tiên Superclass BankAccount balance (parent) name number Generalization Withdraw() Relationship CreateStatement() Subclasses Current Savings Withdraw() GetInterest() Withdraw() Hậu duệ
  37. 37 Ví dụ: Đa thừa kế Một lớp kế thừa từ nhiều lớp khác FlyingThing Animal Đa thừa kế Airplane Helicopter Bird Wolf Horse
  38. 38 Cái gì được thừa kế ? Một lớp con thừa kế các thuộc tính, hành vi và các mối quan hệ từ lớp cha của nó Một lớp con có thể: Bổ sung thuộc tính, hành vi và các mối quan hệ Định nghĩa lại các hành vi Các thuộc tính, hành vi và các mối quan hệ chung được đặt ở mức cao nhất có thể trong cấu trúc phân cấp Sự thừa kế làm nổi bật các điểm tương đồng giữa các lớp
  39. 39 Ví dụ: Cái gì được thừa kế GroundVehicle owner Person Superclass weight licenseNumber 0 * 1 (parent) register() Generalization Subclasses Car Truck Trailer size tonnage getTax()
  40. 40 Ví dụ: Lược đồ lớp
  41. 41 Ví dụ: Lược đồ lớp(tt)
  42. 42 Ví dụ: Lược đồ lớp(tt)
  43. 43 Khai báo lớp BJARNEY Trong ngôn ngữ C++: Header class Rectangle class class_name { { private: permission_label: int width; member; permission_label: int length; Body member; public: void set(int w, int l); }; int area(); NEVER forget this semi-colon at }; the end of the header
  44. 44 Quyền truy cập direct access external
  45. 45 Quyền truy cập (tt)
  46. 46 Ví dụ: Quyền truy cập class Student { Public Interface private: // by default setId() getId() int id; getDept() public: printId() // member functions void setId(); int getId(); char *getDept(); void printId(); };
  47. 47 Ví dụ: Quyền truy cập (tt) Các thành viên thấy tất cả các thành viên private public id setId() getId() getDept() printId()
  48. 48 Ví dụ: Quyền truy cập (tt) Client chỉ được phép truy cập các thành viên public private public id setId() getId() printId() getDept()
  49. 49 Khai báo lớp (tt) James Gosling Trong ngôn ngữ Java Import Statements Class Comment class { Class Name Data Members Methods (incl. Constructor) }
  50. 50 Ví dụ: Khai báo lớp trong Java class Account { private String ownerName; public void setInitialBalance (double bal) { private double balance; balance = bal; public Account( ) { } ownerName = "Unassigned"; balance = 0.0; public void setOwnerName } (String name) { public void add(double amt) { ownerName = name; balance = balance + amt; } } } public void deduct(double amt) { balance = balance - amt; } public double getCurrentBalance( ) { return balance; } public String getOwnerName( ) { return ownerName; } Page 1 Page 2
  51. 51 Làm việc với nhiều file Hầu hết các lớp đều được cài đặt thành 2 files: File (.h) – khai báo lớp: các dữ liệu và các prototype của các phương thức. File code (.cpp) – cài đặt/định nghĩa các phương thức. main.cpp: sử dụng các lớp cpoint.h cpoint.cpp main.cpp class CPoint #include “cpoint.h” #include “cpoint.h” { class CPoint #include “cpoint.h” #include “crectangle.h” { classint CPoint mX , mY; void CPoint::init()#include “cpoint.h” { int m_x , m_y; { void CPoint::Init() void main() public: int m_x , m_y; { void CPoint::Init() { public:void init(); } { CPoint p1; voidpublic:void set(int Init(); aX, int aY); } voidbool print();void Set(int Init(); ax, int ay); void CPoint::set(int} aX, int aY) } voidbool Print(); Set(int ax, int ay); { bool CPoint::Set(int ax, int ay) int getX()void { Print();return mX; } { bool CPoint::Set(int ax, int ay) int intgetY() GetX() { return { return mY; m_x; } } } { }; int intGetY() GetX() { return { return m_y; m_x; } } } }; int GetY() { return m_y; } } }; copyrights © Elhanan Borenstein
  52. 52 File .H // SPECIFICATION FILE ( CPoint .h ) // Specifies the data members and // members function prototypes. #ifndef CPOINT_H #define CPOINT_H class CPoint { public: . . . private: . . . } ; #endif
  53. 53 Dịch và liên kết các files File đặc tả/khai báo Chương trình chính cpoint.h File cài đặt main.cpp cpoint.cpp #include “cpoint.h” Compiler Compiler main.obj cpoint.obj Linker main.exe
  54. 54 Đóng bao và che giấu thông tin Đóng bao: Một lớp C++ cung cấp một cơ chế để đóng gói các dữ liệu và các thao tác trên các dữ liệu đó thành một thực thể Che giấu thông tin: Một lớp C++ cung cấp một cơ chế để chỉ định quyền truy cập trên dữ liệu và phương thức được đóng bao main.cpp: client, cpoint.h: interface, cpoint.cpp: implementation
  55. 55 Lớp và đối tượng class Rectangle Rectangle r1; { Rectangle r2; private: Rectangle r3; int width; int length; public: void set(int w, int l); int area(); int a; }
  56. 56 1 Thiết kế và phát triển các chương trình OO 1 Design your class. Think about : 2 . its essential Develop the characteristics class definition . its behaviours UML diagrams help. (XXXX.h)
  57. 57 2 Thiết kế và phát triển các chương trình OO Create and use 3 4 objects. Implement the class functions. XXXX myVar; (XXXX.cpp) myVar.memFunc(); (myProg.cpp)
  58. 58 Khai báo và sử dụng đối tượng class Rectangle main() { { private: Rectangle r1; Rectangle r2; int width; r1.set(5, 8); int length; cout<<r1.area()<<endl; public: r2.set(8,10); void set(int w, int l); cout<<r2.area()<<endl; int area(); } }
  59. 59 Khai báo và sử dụng đối tượng(tt) #include // các định nghĩa/cài đặt hàm thành viên class circle void circle::store(double r) { { private: radius = r; } double radius; double circle::area(void) { public: return 3.14*radius*radius; } void store(double); void circle::display(void) double area(void); { void display(void); cout << “r = “ << radius << endl; } }; int main(void) { circle c; // một đối tượng của lớp circle c.store(5.0); cout << "The area of circle c is " << c.area() << endl; c.display(); }
  60. 60 Khai báo và sử dụng đối tượng (tt) class Rectangle r1 is statically allocated { private: main() { int width; Rectangle r1; int length; r1.set(5, 8); } public: void set(int w, int l); int area(); r1 width = 5 } length = 8
  61. 61 Khai báo và sử dụng đối tượng (tt) class Rectangle r2 is a pointer to a Rectangle object { main() private: { int width; Rectangle r1; r1.set(5, 8); //dot notation int length; Rectangle *r2; public: r2 = &r1; r2->set(8,10); //arrow notation void set(int w, int l); } int area(); 5000 } r1 r2 width = 58 6000 length = 810 5000???
  62. 62 Khai báo và sử dụng đối tượng (tt) class Rectangle r3 is dynamically allocated { main() private: { Rectangle *r3; int width; r3 = new Rectangle(); int length; r3->set(80,100); //arrow notation public: delete r3; void set(int w, int l); r3 = NULL; } int area(); } r3 6000 5000 NULL5000??? width = 80 length = 100
  63. 63 Khởi tạo đối tượng 1. Bằng cách gán #include • Chỉ làm việc trên các dữ liệu class circle thành viên public { • Không có quyền thao tác trên public: các dữ liệu thành viên double radius; }; int main() { circle c1; // Khai báo một đối tượng của lớp circle c1.radius = 5; // Khởi tạo bằng cách gán circle c2 = {-10}; // Khởi tạo bằng tập hợp, nhưng không hợp lệ }
  64. 64 Khởi tạo đối tượng (tt) #include class circle { ằ private: 2. B ng các hàm thành viên public double radius; public: void setR (double r) • Accessor/Lấy {radius = r;} • Implementor/Đặt double getR () {return radius;} }; int main(void) { circle c; // một đối tượng của lớp circle c.setR(5.0); // khởi tạo một đối tượng với hàm thành viên public cout << "The radius of circle c is " << c.getR() << endl; // truy cập thành viên dữ liệu private với một hàm lấy }
  65. 65 Khởi tạo đối tượng (tt) class Rectangle r2 is a pointer to a Rectangle object { main() private: { Rectangle r1; r1.set(5, 8); int width; //dot notation int length; Rectangle *r2; r2 = &r1; public: r2->set(8,10); } void set(int w, int l); //arrow notation int area(); } r1 and r2 are both initialized by public member function set
  66. 66 Khởi tạo đối tượng (tt) 3. Bằng Constructor class Rectangle { private: • Default constructor int width; • Copy constructor int length; public: • Constructor with parameters • Conversion constructor Rectangle(); Rectangle(const Rectangle &r); They are publicly accessible Rectangle(int w, int l); Have the same name as the class void set(int w, int l); There is no return type int area(); Are used to initialize class data } members They have different signatures
  67. 67 Khởi tạo đối tượng (tt) When a class is declared with no constructors, the compiler automatically assumes default class Rectangle constructor and copy constructor for it. { private: • Default constructor int width; int length; Rectangle :: Rectangle() { }; public: void set(int w, int l); • Copy constructor int area(); } Rectangle :: Rectangle (const Rectangle & r) { width = r.width; length = r.length; };
  68. 68 Khởi tạo đối tượng (tt) • Initialize with default constructor class Rectangle Rectangle r1; { Rectangle *r3 = new Rectangle(); private: int width; int length; • Initialize with copy constructor public: void set(int w, int l); Rectangle r4; r4.set(60,80); int area(); Rectangle r5 = Rectangle(r4); } Rectangle *r6 = new Rectangle(r4);
  69. 69 Khởi tạo đối tượng (tt) class Rectangle If any constructor with any number of parameters is declared, no default { constructor will exist, unless you private: define it. int width; int length; Rectangle r4; // error public: Rectangle(int w, int l) {width =w; length=l;} • Initialize with constructor void set(int w, int l); int area(); Rectangle r5(60,80); } Rectangle *r6 = new Rectangle(60,80);
  70. 70 Khởi tạo đối tượng (tt) Write your own constructors class Rectangle { Rectangle :: Rectangle() private: { width = 20; int width; length = 50; int length; }; public: Hoặc Rectangle :: Rectangle() : width(20), length(50) { } Rectangle(); Rectangle(int w, int l); Rectangle *r7 = new Rectangle(); void set(int w, int l); int area(); r7 } 6000 5000??? 5000 width = 20 length = 50
  71. 71 Khởi tạo đối tượng (tt) With constructors, we have more class Account control over the data members { private: Account :: Account(const Account &a) { char *name; name = new char[strlen(a.name)+1]; double balance; strcpy (name, a.name); unsigned int id; //unique balance = a.balance; public: id = get_unique_id(); }; Account(); Account(const Account &a); Account(const char *person); Account :: Account(const char *person) } { name = new char[strlen(person)+1]; Account :: Account() strcpy (name, person); { balance = 0.0; name = NULL; balance = 0.0; id = get_unique_id(); id = get_unique_id(); }; };
  72. 72 Khởi tạo đối tượng – Conversion constructor A type conversion occurs when the compiler changes the type of an object. An explicit type conversion occurs when the programmer uses a cast in the code to change the type of an object. double x = double(3) / 2; // The value of x is 1.5 An implicit type conversion occurs when the compiler automatically changes the type of an object. int i = 32.4; // The value of i is 32
  73. 73 Conversion constrctor We can tell the compiler how to perform type conversions for user-defined types by defining conversion constructors. A conversion constructor is a constructor whose purpose is to convert an object from some arbitrary type into a user-defined type. The general form of a conversion constructor is className::className(const ArbitraryType& objectName) { // }
  74. 74 Ví dụ: Conversion constructor #ifndef STUDENT_H #include "student.h“ #define STUDENT_H // Constructor class Student Student::Student(char* aName) { { public: int length = strlen(aName) + 1; // Constructor name = new char [length]; Student(char* aName = ""); strcpy(name, aName); private: numUnits = 0; char* name; // Student's name } int numUnits;// Number of units student is #include "student.h" enrolled in void enrol(Student aStudent); }; // #endif void main(void) { enrol("Jim Shooz"); // }
  75. 75 Hủy đối tượng Destructor class Account { Account :: ~Account() { private: delete[] name; char *name; } double balance; unsigned int id; //unique public: Account(); Its name is the class name preceded by a ~ (tilde) Account(const Account &a); It has no argument Account(const char *person); It is used to release dynamically allocated memory and to perform ~Account(); other "cleanup" activities } It is executed automatically when the object goes out of scope
  76. 76 Ví dụ: Hủy đối tượng class Str Str :: Str() { { pData = new char[1]; char *pData; *pData = ‘\0’; int nLength; nLength = 0; }; public: //constructors Str(); Str :: Str(char *s) { Str(char *s); pData = new char[strlen(s)+1]; Str(const Str &str); strcpy(pData, s); nLength = strlen(s); }; //accessors char* get_Data(); int get_Len(); Str :: Str(const Str &str) { int n = str.nLength; //destructor pData = new char[n+1]; ~Str(); nLength = n; strcpy(pData,str.pData); }; };
  77. 77 Ví dụ: Hủy đối tượng (tt) class Str { char *pData; char* Str :: get_Data() int nLength; { return pData; public: }; //constructors Str(); int Str :: get_Len() Str(char *s); { Str(const Str &str); return nLength; }; //accessors char* get_Data(); Str :: ~Str() int get_Len(); { delete[] pData; }; //destructor ~Str(); };
  78. 78 Ví dụ: Hủy đối tượng (tt) class Str { char *pData; int nLength; int main() public: { //constructors int x=3; Str(); Str *pStr1 = new Str(“Joe”); Str(char *s); //initialize from char* Str(const Str &str); Str *pStr2 = new Str(); //initialize with constructor //accessors } char* get_Data(); int get_Len(); //destructor ~Str(); };
  79. 79 Hình ảnh bộ nhớ type value char '\0' char 'J' char 'o' char 'e' char '\0' type var value char * pData address Str object int nLength 0 type var value char * pData address Str object int nLength strlen("joe")+1 type var value int x 3 Str * pStr1 Address Str * pStr2 Address Stack MemoryStack
  80. 80 Các giai đoạn trong thời gian sống của một đối tượng Automatic! Stack Allocate Construct heap: new() bits object Use object Stack Destruct Free bits heap: delete() Up to you!
  81. 81 Các loại phương thức Có các loại hàm thành viên khác nhau trong khai báo của một lớp accessor int CStr :: get_length(); implementor/worker void Rectangle :: set(int, int); helper/utility void Date :: errmsg(const char* msg); constructor Account :: Account(); Account :: Account(const Account& a); Account :: Account(const char *person); destructor Account :: ~Account(); Các phương thức còn lại
  82. 82 Phương thức get/set
  83. 83 Phạm vi Chúng ta có thể sử dụng một biến hoặc một đối tượng chỉ trong một phạm vi cho phép của nó. Các phạm vi: local (or block) scope/cục bộ/khối global scope/toàn cục class scope/lớp file scope/tập tin
  84. 84 Phạm vi cục bộ { In C++ a block of code int x , y = 2; is a section of code x = 1; between { }. { int x2 = 4, int y; A local variable is in x = x2; scope from it’s y = 5; } declaration to the end Scope of x2 and y cout << x << y; of the block }
  85. 85 Phạm vi toàn cục int x = 0; // global x int main(void) Variables that are { declared outside of int x = 2; // 1st local any block or class { int x = 4; // 2nd have global scope. x = 5; ::x = 5; The scoping operator } :: can be used to access x = 3; global variables. return 0; }
  86. 86 class Money { Phạm vi lớp public: A void setDollars (int d); Variables and A private: int dollars; functions declared in }; the class declaration (Money.h) are visible in void Money::setDollars the definitions of the (int d) B { member functions. B if (d >= 0) Money::setDollars() dollars = d; else dollars = 0; }
  87. 87 Phạm vi file To declare a variable static int myVal; void myFun(void); with file scope, declare it outside any int main (void){ block or class and myVal = 0; precede it with the myFun(); keyword static. } void myFun() { It is in scope from the myVal++; declaration to the end of } the file.
  88. 88 Thành viên dữ liệu tĩnh/không tĩnh Thành viên dữ liệu không tĩnh Mỗi một đối tượng của lớp có một bản sao giá trị sở hữu của nó Thành viên tĩnh Như là một biến toàn cục Một bản sao cho một lớp. Ví dụ như bộ đếm
  89. 89 Thành viên dữ liệu tĩnh Rectangle r1; class Rectangle Rectangle r2; { Rectangle r3; private: int width; int length; count static int count; public: r1 r2 width width void set(int w, int l); length length int area(); width } r3 length
  90. 90 Hàm thành viên tĩnh Giống như dữ liệu thành viên tĩnh, là một hàm toàn cục, tất cả các đối tượng của lớp chia sẻ hàm này Không có con trỏ this (sẽ đề cập sau) Không thể truy cập các thành viên không tĩnh của lớp Không phải là hàm thành viên hằng Một hàm thành viên có thể gọi một hàm thành viên tĩnh thuộc lớp đó một cách trực tiếp Một hàm không thành viên có thể gọi một hàm thành viên tĩnh bằng cách: ClassName::staticMemberFunctionName() or objectName.staticMemberFunctionName()
  91. 91 Ví dụ: Thành viên tĩnh Student class -studentCount Student student1; Student student2; +getStudentCount student1 object Student::getStudentCount(); -id student1.setID( 1 ); +Student() student2.setID( 2 ); +getID() class Student +setID( id ) { private: long id; static long studentCount; student2 object public: Student() -id { studentCount++; +Student() } static long getStudentCount() +getID() { return studentCount; +setID( id ) } long getID() { return id; } void setID( long inID ) { id = inID; } }; Sử dụng thành viên tĩnh khi nào ?
  92. 92 Ví dụ: Thành viên tĩnh (tt)
  93. 93 Thành viên dữ liệu hằng Ta đã biết từ khóa const dùng với các biến const int x = 50; Từ khóa const đối với thành viên dữ liệu ? Khi một thành viên dữ liệu được khai báo là const, thành viên đó sẽ giữ nguyên giá trị trong suốt thời gian sống của đối tượng chủ
  94. 94Thành viên dữ liệu hằng (tt) Khởi tạo thành viên dữ liệu hằng khi nào ? Bên trong khai báo lớp? Quá sớm, ta chưa có đối tượng nào, không có chỗ để lưu giá trị Gán trị trong thân constructor? Quá muộn, không đảm bảo hằng không được truy cập trước khi nó được gán Giải pháp: danh sách khởi tạo tại constructor Danh sách khởi tạo của constructor nằm tại định nghĩa của constructor, khi dùng các hàm thành viên, danh sách khởi tạo đảm bảo chúng được khởi tạo trước khi được truy cập
  95. 95 Thành viên dữ liệu hằng (tt) Các hằng của các đối tượng khác nhau (thuộc cùng một lớp) không có quan hệ gì với nhau Ví dụ, một đối tượng thuộc lớp MyClass có hằng foo với giá trị 5, trong khi đó một đối tượng khác cùng thuộc lớp MyClass lại có hằng foo có giá trị 10
  96. 96 Hàm thành viên hằng Khai báo return_type func_name (para_list) const; Định nghĩa return_type func_name (para_list) const { } return_type class_name :: func_name (para_list) const { } Không được thay đổi các thành viên dữ liệu (safe function) Không hợp lệ, nếu một hàm thành viên hằng thay đổi thành viên dữ liệu của lớp
  97. 97 Ví dụ: Hàm thành viên hằng class Time { private : int hrs, mins, secs ; function declaration public : void write ( ) const ; } ; function definition void Time :: write( ) const { cout <<hrs << “:” << mins << “:” << secs << endl; }
  98. 98 Hằng đối tượng Hằng đối tượng Trình biên dịch sẽ đảm bảo rằng không một thành viên dữ liệu nào có thể bị sửa đổi sau khi đối tượng được khởi tạo Kể cả các thành viên public không phải là hằng Khai báo const MyClass x(5); // x //là hằng đối tượng Khi làm việc với hằng đối tượng, ta chỉ có thể gọi các hàm thành viên là hằng - const hoặc tĩnh - static
  99. 99 Con trỏ this Khủng hoảng định danh: Tất cả các đối tượng này Tôi là ai? Một đối tượng có thể tham chiếu đến chính nó bằng cách sử dụng một con trỏ đặc biệt có tên là this Con trỏ this trỏ tới chính các đối tượng Nó cho phép các đối tượng có thể biết được: Nó là ai ? Cũng như cho phép báo cho các đối tượng khác biết: Nó là ai ?
  100. 100 Con trỏ this (tt) Có nhiều cách dùng con trỏ this. Dưới đây là các cách thường dùng: Tránh đụng độ tên Sắp xếp tầng các lời gọi phương thức trên cùng một bản thân đối tượng (gọi nhiều hàm thành viên trên cùng một đối tượng) Truyền dữ liệu xung quanh một đối tượng Xem như là một tham số thứ nhất của hàm thành viên (sẽ đề cập sau)
  101. 101 Con trỏ this (tt) Example 1 – get/set – avoiding name collisions class Student { private: long id; public: long getID() { return id; } void setID( long id ) { this->id = id; } };
  102. 102 Con trỏ this (tt) Example 2 – cascading method calls class Student { private: long id; bool enrolled; public: long getID() { return id; } Student& setID( long id ) { this->id = id; return *this; } bool isEnrolled() { return enrolled; } Student& setEnrolled( bool enrolled ) { this->enrolled = enrolled; return *this; } }; void main() Tại sao kiểu trả về phải là { Student student; tham chiếu ? student.setEnrolled( true ).setID( 1 ); }
  103. 103 Con trỏ this (tt) Example 3 – passing your instance around #include // class Student implmentation using namespace std; Student::Student( char* name, bool enrolled ) { // constants setName( name ); const int MAX_STRING_LENGTH = 256; setEnrolled( enrolled ); const int MAX_STUDENTS = 20; id = studentCount; studentList[ Student::studentCount ] = this; // class Student interface studentCount++; class Student } { private: const char* Student::getName() static long studentCount; { static Student* studentList[ MAX_STUDENTS ]; return name; } char name[ MAX_STRING_LENGTH ]; bool enrolled; void Student::setName( char* name ) long id; { strcpy( this->name, name ); public: } Student( char*, bool ); bool Student::isEnrolled() const char* getName(); { void setName( char* ); return enrolled; bool isEnrolled(); } void setEnrolled( bool ); long getID(); void Student::setEnrolled( bool enrolled ) { static Student* getStudentFromID( long id ); this->enrolled = enrolled; static long getStudentCount(); } };
  104. 104 Con trỏ this (tt) Example 3 – passing your instance around – long Student::getID() // main routine to demonstrate Student { cont’d void main() return id; { } // get students do // class Student static method implmentation { Student* Student::getStudentFromID( long id ) char name[ MAX_STRING_LENGTH ]; { bool enrolled; if ( ( id = 0 ) ) cout > name; return studentList[ id ]; if ( stricmp( name, "end" ) == 0 ) } break; else cout > enrolled; return 0; new Student( name, enrolled ); } } } while( true ); long Student::getStudentCount() { return studentCount; } // class Student static member initialization long Student::studentCount = 0; Student* Student::studentList[ MAX_STUDENTS ];
  105. 105 Con trỏ this (tt) Example 3 – passing your instance around – // printcont’d list of students for( int i = 0; i getName() getID() isEnrolled() << endl; } } Output Student name:Eric enrolled?:1 Student name:Kenny enrolled?:0 Student name:end Student Record name: Eric id: 0 enrolled:1 Student Record name: Kenny id: 1 enrolled:0
  106. 106 Hàm bạn và lớp bạn Các kiểu giao tiếp (interface) của C++ Private: Thành viên của lớp Protected: Lớp thừa kế Public: Phần còn lại của thế giới C++ cung cấp một cơ chế để cung cấp thêm giao tiếp với các thành viên private và protected của lớp (hàm bạn) và để kết nối quan hệ giữa các lớp (lớp bạn) Bạn (friend) Một hàm hoặc một lớp có thể được khai báo như là bạn của lớp khác Bạn của một lớp có quyền truy cập tất cả các thành viên của lớp đó (private, public và protected)
  107. 107 Hàm bạn và lớp bạn (tt) Các tính chất của quan hệ friend: Phải được cho, không được nhận Lớp B là bạn của lớp A, lớp A phải khai báo rõ ràng B là bạn của nó Không đối xứng Không bắc cầu Quan hệ friend có vẻ như vi phạm khái niệm đóng bao (encapsulation) của lập trình hướng đối tượng nhưng có trường hợp lại cần đến nó để cài đặt các mối quan hệ giữa các lớp và khả năng đa năng hóa toán tử trên lớp (sẽ đề cập ở chương sau)
  108. 109 Friends of the Creature class Creature { friend void rejuvenate(Creature & c); friend class Fred; private: int yearOfBirth; public: Creature(int year) { yearOfBirth = year; } int getYearOfBirth() { return yearOfBirth; } }; born1997
  109. 110Friends of the Creature (tt) class Creature { friend void rejuvenate(Creature & c); friend class Fred; private: The function rejuvenate can now access int yearOfBirth; the private attribute yearOfBirth: public: Creature(int year) { void rejuvenate(Creature & c) { c.yearOfBirth = c.yearOfBirth + 5; yearOfBirth = year; } } int getYearOfBirth() { return yearOfBirth; } }; born1997
  110. 111Friends of the Creature (tt) class Creature { friend void rejuvenate(Creature & c); friend class Fred; private: The class Fred can now access the int yearOfBirth; private attribute yearOfBirth: public: Creature(int year) { class Fred { void mature(Creature &c ) { yearOfBirth = year; c.yearOfBirth = c.yearOfBirth - 5; } } int getYearOfBirth() {// return yearOfBirth;} } }; born1997
  111. 112 Quan hệ bạn: Ví dụ #include int main() using namespace std; { class Student Student st1(5), st2(6); { if (st1.sameDept(st2)==true) int dept; cout<<"Same"; public: else cout<<"Different"; Student(int d) {dept=d; } cout<<endl; bool sameDept(const Student &st) { return 0; if (dept==st.dept) return true; } else return false; } }; Kết quả: ?
  112. 113 Quan hệ bạn: Ví dụ (tt) #include using namespace std; class Teacher int main() { { int dept; Student st(5); public: Teacher tch(5); Teacher(int d) { if (st.TsameDept(tch)== true) dept=d; cout<<"Same"; } else cout<<"Different"; }; return 0; } class Student { int dept; public: Không thể truy cập Student(int d) được thành viên private { của lớp Teacher dept=d; } bool TsameDept(const Teacher &tch) { if (dept==tch.dept) return true; else return false; Kết quả: ? } };
  113. 114 Quan hệ bạn: Giải pháp 1 cho ví dụ class Teacher class Student { { int dept; int dept; public: public: Teacher(int d) Student(int d) { { dept=d; dept=d; } } bool TsameDept(Teacher &tch) int getDept() { { if (dept==tch.getDept()) return dept; return true; } else return false; }; } int main() }; { Student st(5); Teacher tch(5); if (st.TsameDept(tch)== true) cout<<"Same"; else cout<<"Different"; Kết quả: ? return 0; }
  114. 115 Quan hệ bạn: Giải pháp 2 cho ví dụ class Teacher class Teacher;//Khai bao truoc { int dept; class Student public: { Teacher(int d) int dept; { dept=d; public: Student(int d) } { friend bool Student::TsameDept(Teacher &tch); }; dept=d; } bool Student::TsameDept(Teacher &tch) bool TsameDept(Teacher &tch); { if (dept==tch.dept) return true; }; else return false; } int main() { Student st(5); Teacher tch(5); Kết quả: ? if (st.TsameDept(tch)== true) cout<<"Same"; else cout<<"Different"; return 0; Hàm bạn của một lớp }
  115. 116 Quan hệ bạn: Giải pháp 3 cho ví dụ class Teacher;//Khai bao truoc bool TsameDept(const Student &st, const class Student Teacher &tch) { int dept; { public: if (st.dept==tch.dept) return true; Student(int d) else return false; { dept=d; } } int main() friend bool TsameDept(const Student &st, { const Teacher &tch); }; Student st(5); class Teacher Teacher tch(5); { if (TsameDept(st, tch)==true) int dept; public: cout<<"Same"; Teacher(int d) else cout<<"Different"; { return 0; dept=d; } } friend bool TsameDept(const Student &st, const Teacher &tch); }; Kết quả: ? Hàm bạn của cả hai
  116. 117 Bạn hay thành viên ? Nếu một hàm cần phải truy cập các thành phần private của hai hoặc nhiều lớp thì dùng hàm bạn, ngược lại, dùng hàm thành viên Sử dụng hàm thành viên nếu có thể được, sử dụng hàm bạn nếu phải bắt buộc Quan hệ bạn có thể ảnh hưởng đến không gian tên toàn cục, nên hạn chế sử dụng (hàm toàn cục và lớp toàn cục)
  117. 118 Lớp gộp/cấu thành Một lớp có thể có các thành viên dữ liệu là các đối tượng của lớp khác Khi một lớp có các đối tượng, các tham chiếu, hoặc các con trỏ trỏ tới lớp khác ta nói nó là một lớp gộp/cấu thành
  118. 119 Lớp gộp/cấu thành (tt) class Transcript{// }; class Address{// }; class Student { public: private: long id; Transcript tr; //Thành viên dữ liệu thuộc lớp Transcript Address addr; //Thành viên dữ liệu thuộc lớp Address float gradeAverage; };
  119. 120 Lớp gộp/cấu thành (tt) class Point const int MAXVERTICES = 10; { enum Colors {WHITE, BLUE, GREEN}; public: class Figure Point(); { Point( const int xv, const int yv ); public: private: Figure(); int x; void setCenter( const Point & p ); int y; void setColor( const int colr ); }; void setVertex( const int n, const Point & p ); private: Point vertex[MAXVERTICES]; // array of //vertices int vCount; // number of vertices Point center; // center of rotation int color; // color };
  120. 121 Lớp gộp/cấu thành (tt) int main() { Figure F; F.setVertex( 0, Point( 1, 1 )); F.setVertex( 1, Point( 10, 2 )); F.setVertex( 2, Point( 8, 10 )); F.setVertex( 3, Point( -2, 2 )); F.setCenter(Point P( 6, 5 ) ); const int FIGCOUNT = 5; Figure figList[FIGCOUNT]; // array of Figures for(int j = 0; j < FIGCOUNT t; j++) figList[j].SetColor( GREEN ); return 0; }
  121. 122 Thứ tự gọi các Constructor/Destructor Constructor cho tất cả các đối tượng thành viên được thực thi theo thứ tự mà chúng xuất hiện trong định nghĩa lớp. Tất cả các constructor thành viên đều được thực thi trước khi constructor của lớp bao nó thực thi Các destructor được gọi thực thi ngược lại với các constructor. Destructor của lớp bao được thực thi trước các destructor của các đối tượng thành viên
  122. 123 Ví dụ: Thứ tự gọi các Constructor/Destructor #include const int MAXVERTICES = 3; Using namespace std; class Figure class Point { { public: public: Figure() { cout << "Figure Point() { cout << "Point constructor\n"; } constructor\n"; } ~Figure() { cout << "Figure ~Point() { cout << "Point destructor\n"; destructor\n"; } } private: }; Point vertex[MAXVERTICES]; // //array of vertices Point center; }; int main() { Kết quả: ? Figure F; return 0; }
  123. 125 Hỏi và Đáp