intTypePromotion=1
zunia.vn Tuyển sinh 2024 dành cho Gen-Z zunia.vn zunia.vn
ADSENSE

Lập trình hướng đối tượng - Chương 9

Chia sẻ: Nguyễn Nhi | Ngày: | Loại File: PDF | Số trang:27

43
lượt xem
2
download
 
  Download Vui lòng tải xuống để xem tài liệu đầy đủ

Tính đa hình • Con trỏ và Lớp dẫn xuất • Dẫn nhập các hàm ảo • Các hàm ảo thuần túy • Áp dụng đa hình

Chủ đề:
Lưu

Nội dung Text: Lập trình hướng đối tượng - Chương 9

  1. Chöông 9 Tính ña hình • Con troû vaø Lôùp daãn xuaát • Daãn nhaäp caùc haøm aûo • Caùc haøm aûo thuaàn tuùy • AÙp duïng ña hình
  2. 270 Chöông 9 Tính ña hình I/ Con troû vaø Lôùp daãn xuaát 1/ Khaùi nieäm Tính ña hình (polymorphism) ñöôïc hoå trôï baèng hai caùch khaùc nhau trong C++ . Caùch 1, ña hình ñöôïc hoå trôï khi bieân dòch chöông trình (compiler) thoâng qua vieäc quaù taûi caùc haøm vaø toaùn töû. Caùch 2, ña hình ñöôïc hoå trôï ôû thôøi ñieåm thöïc thi chöông trình (run-time) thoâng qua caùc haøm aûo. Caùch naøy giuùp laäp trình vieân linh ñoäng hôn. • Cô sôû cuûa haøm aûo vaø ña hình khi thöïc thi chöông trình laø caùc con troû cuûa lôùp daãn xuaát. Chöông 3 coù khaûo saùt veà con troû, moät ñaëc tính môùi cuûa con troû seõ ñöôïc khaûo saùt trong chöông naøy. Neáu p laø moät con troû tôùi lôùp cô sôû, thì coù theå söû duïng p ñeå troû tôùi baát kyø lôùp naøo ñöôïc suy ra töø lôùp cô sôû. Chaúng haïn, coù hai lôùp cô sôû base vaø lôùp daãn xuaát derived keá thöøa base, caùc phaùt bieåu sau ñeàu ñuùng base *p; // base class pointer base base_ob; // object of type base derived derived_ob; // object of type derived // p can, of course, point to base objects p = &base_ob; // p points to base object // p can also point to derived objects without error p = &derived_ob; // p points to derived object Moät con troû cuûa lôùp cô sôû coù theå troû tôùi baát kyø lôùp daãn xuaát naøo cuûa lôùp cô sôû maø khoâng gaây ra baùo loãi khaùc kieåu. Song chæ coù theå truy caäp ñöôïc caùc thaønh phaàn maø lôùp daãn xuaát ñöôïc keá thöøa töø lôùp cô sôû. Bôûi vì con troû cuûa lôùp cô sôû chæ bieát lôùp cô sôû maø thoâi, noù khoâng bieát gì nhöõng thaønh phaàn ñöôïc theâm vaøo bôûi lôùp daãn xuaát.
  3. 271 Chöông 9 Tính ña hình • Moät con troû cuûa lôùp daãn xuaát khoâng theå duøng ñeå truy caäp moät ñoái töôïng cuûa lôùp cô sôû. (Vieäc söû duïng linh hoaït kieåu coù theå duøng ñeå khaéc phuïc haïn cheá noùi treân, nhöng noù khoâng ñöôïc khuyeán khích söû duïng) Caùc pheùp toaùn soá hoïc treân con troû lieân quan ñeán kieåu döõ lieäu maø con troû ñoù ñöôïc khai baùo ñeå troû ñeán. Do ñoù, neáu con troû ñeán moät ñoái töôïng lôùp daãn xuaát, roài taêng noäi dung con troû leân 1. Ñieàu naøy khoâng laøm cho con troû chæ ñeán ñoái töôïng môùi cuûa lôùp daãn xuaát, maø noù seõ chæ ñeán ñoái töôïng môùi cuûa lôùp cô sôû. Ví duï 1.1 Duøng con troû cuûa lôùp cô sôû ñeå truy caäp ñeán lôùp daãn xuaát. // Demonstrate pointer to derived class. #include class base { int x; public: void setx(int i) { x = i; } int getx() { return x; } }; class derived : public base { int y; public: void sety(int i) { y = i; } int gety() { return y; } }; int main() { base *p; // pointer to base type base b_ob; // object of base derived d_ob; // object of derived // use p to access base object p = &b_ob;
  4. 272 Chöông 9 Tính ña hình p->setx(10); // access base object cout
  5. 273 Chöông 9 Tính ña hình Haøm aûo ñöôïc goïi thöïc thi gioáng nhö caùc haøm thaønh phaàn bình thöôøng cuûa lôùp. Tuy nhieân, khi goïi haøm aûo baèng con troû, vieäc hoå trôï tính ña hình trong khi thöïc thi chöông trình seõ xaûy ra. Khi moät con troû troû ñeán moät lôùp daãn xuaát coù chöùa haøm aûo vaø haøm aûo naøy ñöôïc goïi baèng con troû thì trình bieân dòch seõ xaùc ñònh phieân baûn naøo cuûa haøm ñoù seõ ñöôïc thöïc thi. Do ñoù neáu coù hai hay nhieàu lôùp daãn xuaát cuûa moät lôùp cô sôû naøo ñoù, vaø chuùng ñeàu coù chöùa haøm aûo, thì con troû cuûa lôùp cô sôû coù theå troû ñeán caùc ñoái töôïng khaùc nhau cuûa lôùp daãn xuaát noùi treân, töùc laø coù theå goïi ñeán nhieàu phieân baûn khaùc nhau cuûa caùc haøm aûo. • Moät lôùp coù chöùa haøm aûo ñöôïc goïi laø lôùp ña hình. Ví duï 2.1 // A simple example using a virtual function. #include class base { public: int i; base(int x) { i = x; } virtual void func() { cout
  6. 274 Chöông 9 Tính ña hình }; class derived2 : public base { public: derived2(int x) : base(x) {} void func() { cout
  7. 275 Chöông 9 Tính ña hình Vieäc taùi ñònh haøm aûo trong moät lôùp daãn xuaát coù töông töï nhö quaù taûi haøm khoâng ? Caâu traû lôøi laø khoâng. Quaù taûi haøm Haøm aûo Soá löôïng ñoái soá Cho pheùp khaùc bieät Phaûi gioáng nhau Kieåu döõ lieäu cuûa ñoái soá Cho pheùp khaùc bieät Phaûi gioáng nhau Haøm thaønh phaàn cuûa lôùp Khoâng baét buoäc Baét buoäc Haøm taïo Ñöôïc pheùp Khoâng ñöôïc Haøm huûy Khoâng ñöôïc Coù theå Vò trí Vieäc taùi ñònh haøm aûo trong moät lôùp daãn xuaát coøn ñöôïc goïi laø gaùn thöù töï öu tieân cao hôn cho haøm ñoù. 3/ Caùc haøm aûo ñöôïc phaân caáp theo thöù töï keá thöøa. Neáu lôùp daãn xuaát khoâng taùi ñònh haøm aûo naøo ñoù thì lôùp naøy seõ söû duïng phieân baûn haøm cuûa lôùp cô sôû. Ví duï 2.2 // Virtual functions are hierarchical. #include class base { public: int i; base(int x) { i = x; } virtual void func() { cout
  8. 276 Chöông 9 Tính ña hình { cout
  9. 277 Chöông 9 Tính ña hình #include #include class base { public: int i; base(int x) { i = x; } virtual void func() { cout
  10. 278 Chöông 9 Tính ña hình { base *p; derived1 d_ob1(10); derived2 d_ob2(10); int i, j; for(i=0; ifunc(); // call appropriate function } return 0; } Vieäc choïn löïa ñeå thöïc thi phieân baûn haøm aûo naøo (haøm func() cuûa lôùp derived1 hay haøm func() cuûa lôùp derived2) chæ ñöôïc quyeát ñònh trong luùc run-time. Ñieàu naøy khoâng theå naøo thöïc hieän ñöôïc ôû thôøi ñieåm bieân dòch chöông trình. 5/ Söû duïng haøm aûo ñeå trieån khai caùch thöùc giao dieän Ví duï 2.4 // Use virtual function to define interface. #include class area { double dim1, dim2; // dimensions of figure public: void setarea(double d1, double d2) { dim1 = d1; dim2 = d2; }
  11. 279 Chöông 9 Tính ña hình void getdim(double &d1, double &d2) { d1 = dim1; d2 = dim2; } virtual double getarea() { cout
  12. 280 Chöông 9 Tính ña hình triangle t; r.setarea(3.3, 4.5); t.setarea(4.0, 5.0); p = &r; cout
  13. 281 Chöông 9 Tính ña hình distance (double f) { d = f;} virtual void trav_time() { // define here ... } }; Taïo haøm aûo trav_time() cuûa lôùp distance xuaát ra khoaûng thôøi gian caàn thieát ñeå ñi qua khoaûng caùch naøy. Giaû söû raèng ñôn vò chieàu daøi laø mile vaø vaän toác di chuyeån laø 60 mile/hours. Haõy taïo lôùp daãn xuaát metric töø lôùp distance, vôùi haøm aûo trav_time() in ra khoaûng thôøi gian caàn thieát ñeå ñi qua khoaûng caùch treân, tuy nhieân luùc naøy ñôn vò chieàu daøi laø km vaø vaän toác laø 100km/giôø. III/ Caùc haøm aûo thuaàn tuùy (pure virtual function) Moät tröôøng hôïp khaù phoå bieán khi lôùp cô sôû töï noù khoâng phaûi laø moät lôùp hoaøn chænh, luùc ñoù haøm aûo ñöôïc khai baùo giöõ choã chöù khoâng thöïc hieän coâng vieäc cuï theå. Lôùp cô sôû naøy chæ cung caáp moät boä khung goàm caùc haøm vaø bieán vaø ñeå daønh cho caùc lôùp daãn xuaát caùc phaàn ñònh nghóa coøn laïi. Caùc lôùp daãn xuaát phaûi taùi ñònh taát caû caùc haøm aûo khai baùo trong lôùp cô sôû ñoù. Ñeå ñaûm baûo cho ñieàu naøy, C++ hoå trôï moät coâng cuï goïi laø haøm aûo thuaàn tuùy. • Haøm aûo thuaàn tuùy khoâng coù moät ñònh nghiaõ naøo lieân quan ñeán lôùp cô sôû. Noù chæ coù daïng haøm maø thoâi, caùch khai baùo virtual func-name(arg-list) = 0 ; Haøm ñöôïc gaùn trò zero vôùi muïc ñích thoâng baùo cho trình bieân dòch bieát laø khoâng coù gì trong haøm laø lieân quan ñeán lôùp cô sôû. Khi haøm aûo laø moät haøm aûo thuaàn tuùy, noù buoäc caùc lôùp daãn xuaát phaûi taùi ñònh noù, neáu khoâng trình bieân dòch seõ baùo loãi luùc bieân dòch chöông trình. • Neáu moät lôùp coù chöùa haøm aûo thuaàn tuùy, lôùp ñoù ñöôïc goïi laø lôùp tröøu töôïng. Lôùp tröøu töôïng ñöôïc taïo ra vôùi muïc ñích phaûi ñöôïc keá thöøa, khoâng ñöôïc vaø khoâng theå taïo ra ñeå toàn taïi ñôn ñoäc.
  14. 282 Chöông 9 Tính ña hình Tuy nhieân, coù theå taïo ra moät con troû ñeán lôùp tröøu töôïng bôûi vì ñieàu naøy caàn thieát ñeå hoå trôï cho ña hình trong khi run-time. Ñieàu naøy cuõng cho pheùp tham chieáu ñeán moät lôùp tröøu töôïng. • Khi moät haøm aûo ñöôïc keá thöøa, baûn chaát aûo cuûa noù cuõng ñöôïc keá thöøa. Ñieàu naøy coù nghiaõ laø khi moät lôùp daãn xuaát keá thöøa haøm aûo töø lôùp cô sôû, moät lôùp daãn xuaát thöù hai laïi keá thöøa lôùp daãn xuaát thöù nhaát, haøm aûo coù theå ñöôïc ñònh nghiaõ laïi ôû lôùp daãn xuaát thöù hai (cuõng nhö noù ñöôïc ñònh nghiaõ laïi ôû lôùp daãn xuaát thöù nhaát). Ví duï 3.1 Taïo moät lôùp tröøu töôïng #include class area { double dim1, dim2; // dimensions of figure public: void setarea(double d1, double d2) { dim1 = d1; dim2 = d2; } void getdim(double &d1, double &d2) { d1 = dim1; d2 = dim2; } virtual double getarea() = 0; // pure virtual function }; class rectangle : public area { public: double getarea() { double d1, d2; getdim(d1, d2); return d1 * d2; } };
  15. 283 Chöông 9 Tính ña hình class triangle : public area { public: double getarea() { double d1, d2; getdim(d1, d2); return 0.5 * d1 * d2; } }; int main() { area *p; rectangle r; triangle t; r.setarea(3.3, 4.5); t.setarea(4.0, 5.0); p = &r ; cout
  16. 284 Chöông 9 Tính ña hình class derived1 : public base { public: void func() { cout func(); // use derived2's func() return 0; }
  17. 285 Chöông 9 Tính ña hình Baøi taäp III 1. Haõy taïo ra moät ñoái töôïng cho lôùp area trong ví duï 3.1 chöông 9, ñieàu gì seõ xaûy ra ? 2. Trong ví duï 3.2 chöông 9, thöû xoaù phaàn taùi ñònh haøm aûo func() cuûa lôùp derived2, roài cho truy caäp d_ob2. Keát quûa cuûa chöông trình theá naøo ? 3. Taïi sao khoâng theå taïo ra moät ñoái töôïng thuoäc lôùp tröøu töôïng ? IV/ Aùp duïng ña hình Taïi sao caàn söû duïng ña hình ? 1/ Ña hình raát quan troïng vì noù ñôn giaûn hoaù caùc heä thoáng phöùc taïp. • Ña hình laø moät quaù trình aùp duïng moät giao dieän cho hai hay nhieàu tröôøng hôïp töông töï nhau (nhöng khaùc bieät veà maët kyõ thuaät), noù trieån khai tö töôûng "moät giao dieän cho nhieàu phöông thöùc" . Moät giao dieän hay vaø ñôn giaûn ñöôïc duøng ñeå truy caäp ñeán moät soá caùc hoaït ñoäng coù lieân heä vôùi nhau nhöng khaùc nhau, vaø laøm maát ñi söï phöùc taïp giaû taïo cuûa heä thoáng caùc hoaït ñoäng naøy. • Ña hình laøm cho moái quan heä luaän lyù giöõa caùc hoaït ñoäng töông töï nhau ñöôïc trôû neân roõ raøng hôn, ño ñoù noù giuùp cho laäp trình vieân deã daøng hôn trong vieäc ñoïc hieåu vaø baûo trì chöông trình. Moät khi caùc hoaït ñoäng coù lieân quan vôùi nhau ñöôïc truy caäp baèng duy nhaát moät giao dieän, giuùp seõ nhôù hôn. Giao dieän ñoà hoaï treân heä ñieàu haønh Windows hoaëc Macintosh laø moät ñieån hình. 2/ Khaùi nieäm veà lieân keát Lieân keát (binding) lieân quan ñeán OOP vaø ngoân ngöõ C++. Coù hai khaùi nieäm :
  18. 286 Chöông 9 Tính ña hình • Lieân keát sôùm (early binding) gaén lieàn vôùi nhöõng bieán coá coù theå xaùc ñònh ôû thôøi ñieåm bieân dòch chöông trình. Ñaëc bieät, lieân keát sôùm lieân quan ñeán caùc goïi haøm ñöôïc xöû lyù trong luùc bieân dòch bao goàm : - Caùc haøm thoâng thöôøng - Caùc haøm ñöôïc quaù taûi - Caùc haøm thaønh phaàn khoâng phaûi laø haøm aûo - Caùc haøm friend Taát caû caùc thoâng tin veà ñòa chæ caàn thieát cho vieäc goïi caùc haøm treân ñöôïc xaùc ñònh roõ raøng trong luùc bieân dòch. Öu ñieåm : goïi caùc haøm lieân keát sôùm laø kieåu goïi haøm nhanh nhaát. Nhöôïc ñieåm : thieáu tính linh hoaït. • Lieân keát muoän (late binding) gaén lieàn vôùi nhöõng bieán coá xuaát hieän trong luùc thöïc thi chöông trình (run-time). Khi goïi caùc haøm lieân keát muoän, ñiaï chæ cuûa haøm ñöôïc goïi chæ bieát ñöôïc khi run-time. Trong C++, haøm aûo laø moät ñoái töôïng lieân keát muoän. Chæ khi run-time, haøm aûo ñöôïc truy caäp baèng con troû cuûa lôùp cô sôû, chöông trình môùi xaùc ñònh kieåu cuûa ñoái töôïng bò troû vaø bieát ñöôïc phieân baûn naøo cuûa haøm aûo ñöôïc thöïc thi. Öu ñieåm : tính linh hoaït cuûa noù ôû thôøi gian run-time, ñieàu naøy giuùp cho chöông trình goïn gaøng vì khoâng coù nhöõng ñoaïn chöông trình xöû lyù caùc bieán coá ngaãu nhieân trong khi thöïc thi. Nhöôïc ñieåm : chaäm hôn so vôùi lieân keát sôùm, do phaûi qua nhieàu giai ñoaïn trung gian keøm theo vieäc goïi thöïc thi moät haøm lieân keát muoän. Moãi loaïi lieân keát ñeàu coù nhöõng öu khuyeát ñieåm rieâng cuûa noù, neân phaûi caân nhaéc ñeå quyeát ñònh tình huoáng thích hôïp ñeå söû duïng hai loaïi lieân keát noùi treân. Ví duï 4.1 Minh hoïa tö töôûng "moät giao dieän cho nhieàu phöông thöùc" .
  19. 287 Chöông 9 Tính ña hình // Demonstrate virtual functons. #include #include #include class list { public: list *head; // pointer to start of list list *tail; // pointer to end of list list *next; // pointer to next item int num; // value to be stored list() { head = tail = next = NULL; } virtual void store(int i) = 0; virtual int retrieve() = 0; }; // Create a queue type list. class queue : public list { public: void store(int i); int retrieve(); }; void queue::store(int i) { list *item; item = new queue; if(!item) { cout num = i; // put on end of list
  20. 288 Chöông 9 Tính ña hình if(tail) tail->next = item; tail = item; item->next = NULL; if(!head) head = tail; } int queue::retrieve() { int i; list *p; if(!head) { cout num; p = head; head = head->next; delete p; return i; } // Create a stack type list. class stack : public list { public: void store(int i); int retrieve(); }; void stack::store(int i) { list *item; item = new stack; if(!item) {
ADSENSE

CÓ THỂ BẠN MUỐN DOWNLOAD

 

Đồng bộ tài khoản
2=>2