Kỹ thuật lập trình - Chương 7: Quan hệ lớp
7.1 Quanhệlớp
7.2 Dẫnxuấtvàthừakế
7.3 Hàmảovànguyênlý₫ahình/₫axạ
7.4 Vídụthưviệnkhốichứcnăng
Tóm tắt nội dung Kỹ thuật lập trình - Chương 7: Quan hệ lớp, để xem tài liệu hoàn chỉnh bạn click vào nút "TẢI VỀ" ở trên
viên Các hàm thành viên của lớp dẫn xuất có thể truy nhập thành viên "protected" ₫ịnh nghĩa ở lớp cơ sở, nhưng cũng không thể truy nhập các thành viên "private" ₫ịnh nghĩa ở lớp cơ sở Phản ví dụ: Rectangle rect(0,0,50,100); Square square(0,0,50); square.TL = 10; Lớp dẫn xuất ₫ược "thừa kế" cấu trúc dữ liệu và các phép toán ₫ã ₫ược ₫ịnh nghĩa trong lớp cơ sở, nhưng không nhất thiết có quyền sử dụng trực tiếp, mà phải qua các phép toán (các hàm công cộng hoặc hàm public) Quyền truy nhập của các thành viên "public" và "protected" ở lớp dẫn xuất ₫ược giữ nguyên trong lớp cơ sở 15 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Thuộc tính truy nhập kế thừa Thuộc tính kế thừa của lớp dẫn xuất Y Thuộc tính truy nhập của các thành viên lớp cơ sở X class Y: private X class Y: public X private Được kế thừa nhưng các thành viên của X không thể truy nhập trong Y protected Các thành viên của X sẽ trở thành các thành viên private của Y và có thể ₫ược truy nhập trong Y Các thành viên của X sẽ trở thành các thành viên protected của Y và có thể truy nhập trong Y public Thành viên của X sẽ trở thành thành viên private của Y và có thể truy nhập trong Y Thành viên của X sẽ trở thành thành viên public của Y và có thể truy nhập trong Y 16 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Ví dụ void func2(int a, int b) {...} int xy; class X { private: int x1; protected: int x2; public: int x3; int xy; X(int a, int b, int c) { x1 = a; x2 = b; x3 = xy = c; } void func1(int, int); void func2(int, int); }; void X::func1(int i, int j) {...} void X::func2(int k, int l) {...} 17 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT class Y:public X { private: int y1; public: int y2; int xy; Y(int d, int e, int f, int g, int h):X(d, e, f) { y1 = g; y2 = xy = h; } void func2(int, int); }; void Y::func2(int m, int n) { int a, b; x1 = m; //Error, x1 is private in the basic class X x2 = m; x3 = m; xy = m; X::xy = m; ::xy = m; y1 = n; y2 = n; 18 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT func1(a,b); OK, X::func1(...) X::func2(a,b); OK, X::func2(...) ::func2(a,b) } void f() { const int a = 12; Y objY(3, 4, 5, 6, 7); objY.x1 = a; //Error, x1 is private objY.x2 = a; //Error, x2 is protected objY.x3 = a; objY.xy = a; objY.y1 = a; //Error, y1 is private objY.y2 = a; objY.X::xy = a; objY.func1(a, a); objY.func2(a, a); } 19 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Chuyển ₫ổi kiểu ₫ối tượng Một ₫ối tượng hay con trỏ, hoặc tham chiếu ₫ối tượng kiểu lớp dẫn xuất sẽ có thể ₫ược chuyển ₫ổi kiểu tự ₫ộng về kiểu lớp cơ sở (nếu ₫ược kế thừa public) nhưng không ₫ảm bảo theo chiều ngược. Ví dụ: class X { ... X(...){...} ... }; class Y:public X { ... Y(...):X(...){...} ... }; X objX(...); Y objY(...); X* xp = &objX; //OK X* xp = &objY; //OK Y* yp = &objX; //Error Y* yp = (Y*)&objX; //OK, but not guaranteed! Chuyển ₫ổi kiểu tự ₫ộng cho ₫ối tượng có kiểu lớp cơ sở sang kiểu lớp dẫn xuất sẽ không thể thực hiện vì không ₫ảm bảo ₫ược quyền truy nhập của các thành viên của lớp cơ sở, chắc chắn không ₫ược nếu kế thừa private. 20 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Chuyển ₫ổi kiểu ₫ối tượng Ví dụ: class X { public: int x; }; class Y:private X { }; void f() { Y objY; X *xp; xp = &objY; //Error xp = (X*) &objY; xp->x = 5; } 21 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT 7.3 Hàm ảo và cơ chế ₫a hình/₫a xạ Trong quá trình liên kết, lời gọi các hàm và hàm thành viên thông thường ₫ược chuyển thành các lệnh nhảy tới ₫ịa chỉ cụ thể của mã thực hiện hàm => "liên kết tĩnh" Vấn ₫ề thực tế: — Các ₫ối tượng ₫a dạng, mặc dù giao diện giống nhau (phép toán giống nhau), nhưng cách thực hiện khác nhau => thực thi như thế nào? — Một chương trình ứng dụng chứa nhiều kiểu ₫ối tượng (₫ối tượng thuộc các lớp khác nhau, có thể có cùng kiểu cơ sở) => quản lý các ₫ối tượng như thế nào, trong một danh sách hay nhiều danh sách khác nhau? 22 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Vấn ₫ề của cơ chế "liên kết tĩnh" Xem lại chương trình trước, hàm Rectangle::draw ₫ều in ra tên "Rectangle" => chưa hợp lý nên cần ₫ược ₫ịnh nghĩa lại ở các lớp dẫn xuất void Square::draw() { std::cout << "\nSquare:\t[" << getTL() << getBR() << ']'; } void TextBox::draw() { std::cout << "\nTextbox:\t[" << getTL() << getBR() << ' ' << Text << ']'; } 23 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Chương trình minh họa 1 void main() { Rectangle rect(0,0,50,100); Square square(0,0,50); TextBox text("Hello"); rect.draw(); square.draw(); text.draw(); getch(); std::cout << "\n\nNow they are moved..."; rect.move(10,20); square.move(10,20); text.move(10,20); getch(); std::cout << "\n\nNow they are resized..."; rect.resize(2,2); square.resize(2); text.resize(2,2); getch(); } 24 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Kết quả: Như ý muốn? Rectangle: [(0,0)(50,100)] Square: [(0,0)(50,50)] Textbox: [(0,0)(10,10) Hello] Now they are moved... Rectangle: [(10,20)(60,120)] Rectangle: [(10,20)(60,70)] Rectangle: [(10,20)(20,30)] Now they are resized... Rectangle: [(20,40)(120,240)] Rectangle: [(20,40)(120,140)] Rectangle: [(20,40)(40,60)] Gọi hàm draw() của Rectangle! 25 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Chương trình minh họa 2 void main() { const N =3; Rectangle rect(0,0,50,100); Square square(0,0,50); TextBox text("Hello"); Rectangle* shapes[N] = {&rect, &square, &text}; for (int i = 0; i < N; ++i) shapes[i]->draw(); getch(); } Quản lý các ₫ối tượng chung trong một danh sách nhờ cơ chế dẫn xuất! Kết quả: các hàm thành viên của lớp dẫn xuất cũng không ₫ược gọi Rectangle: [(0,0)(50,100)] Rectangle: [(0,0)(50,50)] Rectangle: [(0,0)(10,10)] 26 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Giải pháp: Hàm ảo class Rectangle { ... public: ... virtual void draw(); } 27 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Kết quả: Nhưmong muốn! Rectangle: [(0,0)(50,100)] Square: [(0,0)(50,50)] Textbox: [(0,0)(10,10) Hello] Now they are moved... Rectangle: [(10,20)(60,120)] Square: [(10,20)(60,70)] Textbox: [(10,20)(20,30) Hello] Now they are resized... Rectangle: [(20,40)(120,240)] Square: [(20,40)(120,140)] Textbox: [(20,40)(40,60) Hello] Chương trình 1 Rectangle: [(0,0)(50,100)] Square: [(0,0)(50,50)] Textbox: [(0,0)(10,10) Hello] Chương trình 2 28 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Hàm ảo class X { ... public: virtual void f1() {...} virtual void f2() {...} virtual void f3() {...} void f4() {...} }; void function() { Y y; X* px = &y; //Typ-Convert Y* to X* px->f1(); //virtual function Y::f1() px->f2(); //virtual function X::f2() px->f3(); //virtual function X::f3() px->f4(); //function X::f4() } class Y:public X { ... public: void f1() {...} void f2(int a) {...} char f3() {...} void f4() {...} }; 29 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Ví dụ hàm ảo class X { protected: int x; public: X(int x_init) { x = x_init;} virtual void print(); }; class Y:public X { protected: int y; public: Y(int x_init, int y_init):X(x_init) {y = y_init;} void print(); }; class Z:public Y { protected: int z; public: Z(int x_init, int y_init, int z_init):Y(x_init, y_init) {z = z_init;} void print(); }; 30 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT class U:public Y { protected: int u; public: Z(int x_init, int y_init, int u_init):Y(x_init, y_init) {u = u_init;} void print(); }; void X::print() { cout << “Data of Class X: “ << x << endl; } void Y::print() { cout << “Data of Class X+Y: “ << x + y << endl; } void Z::print() { cout << “Data of Class X+Y+Z: “ << x + y + z << endl; } void U::print() { cout << “Data of Class X+Y+U: “ << x + y + u << endl; } 31 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT void print_data(X* px) { px->print(); } main() { X* pobjX = new X(1); Y* pobjY = new Y(10, 20); Z* pobjZ = new Z(100, 200, 300); U* pobjU = new U(1000, 2000, 3000); print_data(pobjX); print_data(pobjY); print_data(pobjZ); print_data(pobjU); delete pobjX; delete pobjY; delete pobjZ; delete pobjU; } main() { int x; X *pobj[4]; pobj[0] = new X(1); pobj[1] = new Y(10, 20); pobj[2] = new Z(100, 200, 300); pobj[3] = new U(1000, 2000, 3000); for(x = 0; x < 4; x++) print_data(pobj[x]); delete[4] pobj; } Data of Class X: 1 Data of Class X+Y: 30 Data of Class X+Y+Z: 600 Data of Class X+Y+U: 6000 Kết quả: 32 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT 7.4 Ví dụ thư viện khối chức năng Bài toán: — Xây dựng một thư viện các khối chức năng phục vụ tính toán và mô phỏng tương tự trong SIMULINK — Viết chương trình minh họa sử dụng ₫ơn giản Ví dụ một sơ ₫ồ khối StaticGain Limiter IntegratorSum0 33 © 2 0 0 4 , H O À N G M I N H S Ơ N Chương 7: Quan hệ lớp © 2007 AC - HUT Biểu ₫ồ lớp
File đính kèm:
- C7_Class_Relationship.pdf