Bài giảng môn Lập trình hướng đối tượng - Chương 4: Template

pdf 17 trang phuongnguyen 5680
Bạn đang xem tài liệu "Bài giảng môn Lập trình hướng đối tượng - Chương 4: Template", để 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:

  • pdfbai_giang_mon_lap_trinh_huong_doi_tuong_chuong_4_template.pdf

Nội dung text: Bài giảng môn Lập trình hướng đối tượng - Chương 4: Template

  1. Ch ươ ng 4: Template 4.1. Dn nh p: • Hãy vi t hàm tìm s nh nh t trong 2 s int, double, float, CComplex. • Hãy vi t l p stack đ l ưu int, double, float, CComplex. 4.2. Gi i thi u • Template là m t c ơ ch giúp trình biên d ch t o ra hàm ho c l p t ươ ng ng v i các ki u d li u khác nhau. Bng cách dùng template, ta ch c n đnh ngh ĩa duy nh t mt hàm ho c m t l p và sau đĩ dùng chung đnh ngh ĩa này cho các ki u d li u khác nhau, thay vì ph i t o ra các hàm ho c các l p riêng cho m i ki u d li u. • Template làm gi m đáng k kích th ưc source code, đ ng th i t ăng tính linh ho t ca source code mà khơng làm gi m s an tồn v ki u d li u. • Ví d ụ 1 (v ề function template) : o ð vi t hàm tr v giá tr nh nh t cho nhi u ki u d li u khác nhau, n u khơng dùng template, ta ph i đ nh ngh ĩa ch ng nhi u hàm: // min for ints int Min( int a, int b ){ return ( a T Min( T a, T b ){ return ( a < b ) ? a : b; } int main(){ int a = 3, b = 4; float x = 5.0, y = 6.0; cout<< "Min = " <<Min(2, 3)<<endl; cout<< "Min = " <<Min(a, b)<<endl; cout<< "Min = " <<Min(x, y)<<endl; return 0; Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 1
  2. } Kt qu xu t ra màn hình: Min = 2 Min = 3 Min = 5 • Ví d ụ 2 (v ề class template) : o ð t o lp stack lưu các ki u d li u khác nhau, ta ph i đnh ngh ĩa nhi u lp t ươ ng ng cho t ng ki u d li u khác nhau. // Stack for int class CStack_int { static const int m_nMaxSize = 100; int m_nTop; int m_pStackBuffer[m_nMaxSize]; public : CStack_int(); void Push( const int nItem ); int Pop(); }; // Stack for double class CStack_double { static const int m_nMaxSize = 100; int m_nTop; double m_pStackBuffer[m_nMaxSize]; public : CStack_double(); void Push( const double dItem ); double Pop(); }; o Nu dùng template, ta ch c n đ nh ngh ĩa l p m t l n, và dùng đnh ngh ĩa này cho các lo i d li u khác nhau nh ư sau: template class CStack { static const int m_nMaxSize = i; int m_nTop; T m_pStackBuffer[i]; public : CStack(); void Push( const T& item ); T& Pop(); }; // Create stack of unsigned longs CStack stack1; Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 2
  3. // Uses code created above CStack stack2; // Generates new code CStack stack3; // Generates stack of CComplex objects CStack stack4; int main() { // return 0; } o Trong ví d này, class template CStack dùng 2 tham s : type T và int i . Khi dùng class template, ta cĩ th gi m t ki u d li u b t k ỳ (k c struct và class) vào tham s T, tham s i đưc truy n m t h ng s nguyên. o Vì i là m t hng s đưc đ nh ngh ĩa th i đim d ch, nên ta cĩ th khai báo m t m ng i ph n t nh ư trên. o Ta cĩ th dùng class template đ t o ra m t h các l p cho các ki u d li u khác nhau. 4.3. Class template 4.3.1. To m t class template ð t o m t class template, ta ph i làm 2 vi c: • ðnh ngh ĩa class template • ðnh ngh ĩa các ph ươ ng th c c a class template. 4.3.1.1. ðnh ngh ĩa class template • Cú pháp : template-declaration : template declaration template-argument-list : template-argument template -argument-list , template-argument template-argument : type-argument argument-declaration type-argument : class identifier typename identifier • Tham s c a template (c class template và function template) cĩ th là m t ki u c th (gi ng nh ư m t khai báo bi n). Ví d : template // Tham s th 2 cĩ ki u c th là int Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 3
  4. class TestClass { public : char buffer[i]; T testFunc(T* p1 ); }; • Trong danh sách tham s c a template (c function template và class template), hai t khĩa class và typename là t ươ ng đươ ng. Ví d hai cách vi t sau là hồn tồn tươ ng đươ ng: // Cách 1: dùng t khố class template class X { // }; // Cách 2: dùng t khĩa typename template class X { // }; • Tham s c a m t class template cĩ th là m t khai báo class template. Ví d : template class T1 , typename T2> class Y { // }; • Ví d 4: template struct str1 { T t; }; • Nu mu n truy xu t vào thành ph n c a m t tham s c a class template, ta ph i dùng t khố typename . Ví d : template class X { typename T::Y m_y; // treat Y as a type }; 4.3.1.2. ðnh ngh ĩa các ph ươ ng th c c a class template • Luơn cĩ khai báo template đ u c a đ nh ngh ĩa ph ươ ng th c. • Tên c a template v i các tham s đưc đ t tr ưc tốn t l y ph m vi. • Sau tốn t l y ph m vi là tên c a ph ươ ng th c. • Ví d : Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 4
  5. // ðnh ngh ĩa class template template class TempClass { T m_TArray[i]; public : TempClass(); ~TempClass(); int MemberSet(T, int ); }; // Constructor template // Luơn cĩ k.báo template đ u. TempClass ::TempClass() { // } // Destructor template // Luơn cĩ k.báo template đ u. TempClass ::~TempClass() { // } // Phươ ng th c MemberSet ca class template template // Luơn cĩ k.báo template đ u. int TempClass ::MemberSet( T a, int b ) { if ( ( b >= 0 ) && (b test1; Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 5
  6. • Nu tham s c a class template là m t ki u c th (t c khơng ph i là tham s v i t khố typename ho c class đ ng tr ưc), thì khi truy n đ i s , ta ph i truy n giá tr h ng. Ví d : TempClass test1; // OK int x = 6; TempClass test2; // L i! ði s th 2 ph i là h ng. const int y = 6; TempClass test2; // OK 4.3.1.4. Ví d v vi c to và dùng class template • Sau đây là m t ví d t ươ ng đi hồn ch nh v m t class template CGrid . Ví d này đưc t ch c thành 2 files: Grid.h và Main.cpp : • File Grid.h (file này đnh ngh ĩa class template CGrid và các ph ươ ng th c c a nĩ): // File name: Grid.h template class CGrid { public : CGrid( int nWidth = m_snDefaultWidth, int nHeight = m_snDefaultHeight); CGrid( const CGrid & src); ~CGrid(); CGrid & operator =( const CGrid & rhs); void SetElementAt( int x, int y, const T& inElem); T& GetElementAt( int x, int y); const T& GetElementAt( int x, int y) const ; int GetHeight() const { return m_Height; } int GetWidth() const { return m_Width; } static const int m_snDefaultWidth = 10; static const int m_snDefaultHeight = 10; protected : void CopyFrom( const CGrid & src); T m_Cells; int m_Width, m_Height; }; // Kh i t o các thành ph n d li u t ĩnh (static) template const int CGrid ::m_snDefaultWidth; template const int CGrid ::m_snDefaultHeight; // Constructor bình th ưng template CGrid ::CGrid( int nWidth, int nHeight) : m_Width(nWidth), m_Height(nHeight) { m_Cells = new T* [m_Width]; for (int i = 0; i < m_Width; i++) { m_Cells[i] = new T[m_Height]; Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 6
  7. } } // Constructor sao chép template CGrid ::CGrid( const CGrid & src) { CopyFrom(src); } // Destructor template CGrid ::~CGrid() { // Free the old memory. for (int i = 0; i void CGrid ::CopyFrom( const CGrid & src) { int i, j; m_Width = src.m_Width; m_Height = src.m_Height; m_Cells = new T* [m_Width]; for (i = 0; i CGrid & CGrid :: operator =( const CGrid & rhs) { // Check for self-assignment. if (this == &rhs) { return (* this ); } // Free the old memory. for (int i = 0; i < m_Width; i++) { delete [] m_Cells[i]; } delete [] m_Cells; // Copy the new memory. CopyFrom(rhs); return (* this ); } Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 7
  8. // Ph ươ ng th c SetElementAt template void CGrid ::SetElementAt( int x, int y, const T& inElem) { m_Cells[x][y] = inElem; } // Ph ươ ng th c GetElementAt template T& CGrid ::GetElementAt( int x, int y) { return (m_Cells[x][y]); } // Ph ươ ng th c h ng GetElementAt template const T& CGrid ::GetElementAt( int x, int y) const { return (m_Cells[x][y]); } • File Main.cpp (file này dùng class template CGrid ): // File name: Main.cpp #include “Grid.h” int main( int argc, char argv) { // Declares a grid that stores ints (instantiation) CGrid myIntGrid; myIntGrid.SetElementAt(0, 0, 10); int x = myIntGrid.GetElementAt(0, 0); CGrid grid2(myIntGrid); CGrid anotherIntGrid = grid2; return 0; } Câu h i: 1) Hãy so sánh cách t ch c file cúa ví d này v i cách t ch c file ca ví d v l p CComplex trong ch ươ ng 3 và cho nh n xét. Gi i thích t i sao c n cĩ s khác bi t đĩ. 2) Nu mu n l ưu m t l ưi (hi u theo ngh ĩa m ng 2 chi u) các s ph c thay vì m t lưi các s nguyên nh ư trong hàm main() trên, thì ta ph i làm sao ? 3) Trong các cách vi t sau đây, nh ng cách vi t nào đưc ch p nh n? // Case A void ProcessIntGrid(CGrid & nGrid) { // } // Case B void ProcessIntGrid(CGrid<>& nGrid) { // Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 8
  9. } // Case C void ProcessIntGrid(CGrid& nGrid) { // } 4) Nu ta vi t các đon code nh ư sau, trình biên d ch cĩ ch p nh n khơng, gi i thích ? // Case A CGrid test; // Case B CGrid myIntGrid; // Declares a grid that stores CComplex int c; myIntGrid.SetElementAt(0, 0, c); // Case D CGrid myIntGrid; // Declares a grid that stores ints CComplex c; myIntGrid.SetElementAt(0, 0, c); // Case E CGrid myStringGrid; myStringGrid.SetElementAt(2, 2, “hello”); // Case F CGrid > GridOfVectors; vector myVector; GridOfVectors.SetElementAt(5, 6, myVector); // Case G CGrid > GridOfVectors; // Note the extra space! vector myVector; GridOfVectors.SetElementAt(5, 6, myVector); // Case H CGrid * myGridp = new CGrid (); myGridp->SetElementAt(0, 0, 10); int x = myGridp->GetElementAt(0, 0); delete myGridp; 4.3.2. Trình biên d ch x lý template nh ư th nào • Khi g p đ nh ngh ĩa c a m t template (class template, function template, method template), trình biên dch (TBD) ch ki m tra li cú pháp c a template, nh ưng khơng biên d ch và t o code cho template. B i vì ti th i đim đĩ, TBD khơng bi t ki u d li u mà template s d ng (TBD khơng th biên d ch đ t o code cho câu l nh đ i lo i nh ư x = y n u nĩ khơng bi t bi n x và y thu c ki u d li u nào). Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 9
  10. • Khi TBD g p m t th hi n c a template (instantiation of the template), ví d CGrid myIntGrid , nĩ s t o code cho phiên b n int ca template CGrid bng cách thay t t c các tên T bng int trong đnh ngh ĩa c a class template, đ to thành ki u d li u CGrid . ðiu này gi i thích t i sao ta ph i vi t CGrid trong các đnh ngh ĩa các ph ươ ng th c c a class template. • Nu TBD g p m t instantiation khác c a template, ví d CGrid myComplexGrid , nĩ t o m t phiên b n khác c a class template CGrid t ươ ng ng v i CComplex, t o thành ki u d li u CGrid . • Nu trong ch ươ ng trình khơng cĩ b t k ỳ instantiation ca class template, thì class template và đnh ngh ĩa c a các ph ươ ng th c ca nĩ s khơng đưc d ch và khơng đưc t o ra. 4.3.2.1. C th hố cĩ ch n l c (selective instantiation) • ð ti t ki m th i gian d ch và kích th ưc c a ch ươ ng trình, TBD ch t o ra code cho nh ng ph ươ ng th c (c a class template) mà th c s đưc g i trong ch ươ ng trình cho m t ki u d li u c th nào đĩ. • Ví d , đ i v i đon ch ươ ng trình ph n 4.2.1.4, gi s ta ch cĩ đon code sau trong hàm main() : Grid myIntGrid; myIntGrid.SetElementAt(0, 0, 10); Thì TBD s ch sinh ra code cho các ph ươ ng th c SetElement() , constructor m c đnh , destroctor cho phiên b n int ca class template CGrid . TBD s khơng t o các ph ươ ng th c nh ư constructor sao chép , tốn t gán , GetHeight() v.v (m c dù ta cĩ đnh ngh ĩa các ph ươ ng th c này trong class template CGrid). 4.3.2.2. Yêu c u đ i v i các ki u d li u • Khi đnh ngh ĩa các class template, cĩ ngh ĩa là ta vi t ch ươ ng trình đc l p v i ki u d li u. ðiu đĩ cĩ ngh ĩa là ta đã gi đ nh m t s điu v các tham s ki u đưc dùng trong các class template. Ví d , trong class template CGrid, ta gi s rng ki u d li u T s cĩ constructor m c đ nh đ th c hi n vi c kh i t o m ng (xem l i ví d ph n 4.2.1.4) và mt tốn t gán đ cĩ th th c hi n đưc dịng lnh (trong ph ươ ng th c SetElement() ): m_Cells[x][y] = inElem; • Nu ta th c hi n vi c c th hố class template cho mơt ki u d li u mà khơng h tr ph ươ ng th c mà ta gi đ nh, trình biên d ch s báo l i khi ta g i m t ph ươ ng th c c a class template mà trong ph ươ ng th c đĩ cĩ s d ng ph ươ ng th c gi đnh mà ki u d li u truy n vào tham s c a class template khơng h tr . • Ví d , n u ta khơng đ nh ngh ĩa tốn gán và contructor m c đ nh cho l p CComplex, và gi s ta th c hi n vi c c th hố class template CGrid cho l p CComplex, khi đĩ trình TBD s báo l i khi ta g i ph ươ ng th c SetElement() ca class template CGrid. Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 10
  11. 4.3.3. T ch c file cho các template Vì class template là các “m u” đ TBD cĩ th c ăn c vào đĩ mà t o ra các l p c th và các ph ươ ng th c c th cho m t ki u d li u c th khi ta th c hi n vi c c th hố class template. Do đĩ đnh ngh ĩa c a class template và đnh ngh ĩa c a các ph ươ ng th c c a class template ph i đưc trình biên d ch nhìn th y khi nĩ gp m t instantiation c a class template . ð đ t đưc điu này, ta cĩ th t ch c file cho class template theo m t s cách sau đây. 4.3.3.1. Dùng header files 4.3.3.1.1. Cách 1: • ðt đ nh ngh ĩa c a class template và đnh ngh ĩa c a các ph ươ ng th c c a class template trong cùng m t file header, gi s tempXYZ.h . • Include file tempXYZ.h vào các file cĩ s d ng các ph ươ ng th c c a class template. • Ví d : ch ươ ng trình trong ph n 4.2.1.4 t ch c class template CGrid theo cách này. 4.3.3.1.2. Cách 2: • ðt đ nh ngh ĩa c a class template trong m t file .h riêng, ví d Grid.h . • ðt đ nh ngh ĩa c a các ph ươ ng th c c a class template trong các file .h riêng, ví d GridMethods_1.h , GridMethods_2.h v.v • Include các file GridMethods_1.h , GridMethods_2.h, v.v vào file Grid.h (nh là ph i include sau khi đ nh ngh ĩa class template) . Ví d : // Grid.h template class CGrid { // Class definition omitted for brevity }; #include “GridMethods_1.h” // Contains defs of CGrid’s methods #include “GridMethods_2.h” // Contains defs of CGrid’s methods • Include file Grid.h vào các file ngu n cĩ s dng class template ta v a t o, ví d : // main.cpp: in this file we use class template CGrid #include "Grid.h" int main() { // } 4.3.3.2. Dùng source files Mt s ng ưi khơng thích đ t ph n cài đt các ph ươ ng th c c a class template vào trong header file (vì cĩ v kỳ l ). Trong tr ưng h p đĩ, ta cĩ th đ t đ nh ngh ĩa cho các ph ươ ng Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 11
  12. th c c a class template vào trong source file (file .cpp). Cách làm nh ư sau (ví d cho class template CGrid): • ðt đ nh ngh ĩa c a class template vào file Grid.h • ðt đ nh ngh ĩa c a các ph ươ ng th c c a class template vào file Grid.cpp • Include file Grid.cpp vào file Grid.h nh ư sau: // Grid.h template class CGrid { // Class definition omitted for brevity }; #include “Grid.cpp” // contains defs of methods • Include file Grid.h vào các file ngu n cĩ s d ng class template ta v a t o, ví d : // Main.cpp: In this file, we use class template CGrid #include "Grid.h" int main() { // } 4.3.4. Tham s c a template • Khơng gi i h n s l ưng các tham s c a class template (function template c ũng vy). • Tham s c a template (class template và function template) khơng nh t thi t ph i là m t ki u d li u, chúng cĩ th là m t tham s d ng “bi n s ” (nontype parameter). • Tham s c a template cĩ th nh n đ i s m c đ nh. 4.3.4.1. Nontype template parameters • Tham s c a template cĩ th là các bi n thu c các ki u d li u bình th ưng nh ư: int, enum, pointer, reference. Các tham s này khơng cĩ t khố typename ho c class đi kèm. • Giá tr c a các tham s này đưc bi t tr ưc khi template đưc d ch (vì TBD to ra code cho template b ng cách thay th giá tr c a các tham s c a template tr ưc, ri sau đĩ m i d ch). Do v y ta cĩ th dùng các giá tr này đ c p phát m ng t ĩnh. template class CGrid { public : void SetElementAt( int x, int y, const T& nElem); T& GetElementAt( int x, int y); const T& GetElementAt( int x, int y) const ; int GetHeight() const { return HEIGHT; } int GetWidth() const { return WIDTH; } protected : Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 12
  13. // Dùng nontype parameter c a template đ khai báo m ng tĩnh T m_Cells[WIDTH][HEIGHT] ; }; // ðnh ngh ĩa các ph ươ ng th c template void CGrid ::SetElementAt( int x, int y, const T& nElem) { m_Cells[x][y] = nElem; } template T& CGrid ::GetElementAt( int x, int y) { return m_Cells[x][y]; } template const T& CGrid ::GetElementAt( int x, int y) const { return m_Cells[x][y]; } // ð c th hố cho l p này, ta làm nh ư sau: Grid myGrid; Grid anotherGrid; myGrid.SetElementAt(2, 3, 45); anotherGrid = myGrid; cout testGrid; // Case B const int height = 10; CGrid testGrid; 4.3.4.2. Tham s m c đ nh • C++ cho phép dùng tham s m c đ nh cho template t ươ ng t nh ư tham s m c đnh c a hàm. • Lu t v truy n tham s m c đ nh cho template c ũng gi ng nh ư truy n tham s mc đ nh cho hàm: o Dùng tham s m c đ nh m t cách liên t c. o Dùng tham s m c đ nh b t đ u t ph i sang sang trái. • Ví d : // ðnh ngh ĩa class template template Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 13
  14. class CGrid { // }; // ð.ngh ĩa p.th c: khơng c n ch đ nh l i giá tr c a th.s m c đ nh template void CGrid ::SetElementAt( int x, int y, const T& inElem) { mCells[x][y] = inElem; } // C th hố class template CGrid dùng tham s m c đ nh CGrid myGrid; CGrid anotherGrid; 4.3.5. Method template • Ta khơng th gán m t đ i t ưng thu c l p CGrid cho m t đ i t ưng thu c lp CGrid , điu này đơi khi khơng thu n ti n l m. Method template cĩ th giúp gi i quy t v n đ này. • C++ cho phép template hố riêng t ng ph ươ ng th c c a l p. • Ph ươ ng th c đưc vi t d ưi d ng template (template hố) cĩ th là ph ươ ng th c ca m t class template ho c ph ươ ng th c c a m t l p bình th ưng. • Ph ươ ng th c o và destructor khơng đưc phép là method template. • Method template khơng thay th các ph ươ ng th c khơng template cĩ cùng tên. • Ví d : o Source code: template class CGrid { public : CGrid( int nWidth = kDefaultWidth, int nHeight = kDefaultHeight); CGrid( const CGrid & src); // Constructor sao chép là m t method template template CGrid( const CGrid & src); ~CGrid(); CGrid & operator =( const CGrid & rhs); // Tốn t = là m t method template template CGrid & operator =( const CGrid & rhs); void SetElementAt( int x, int y, const T& inElem); T& SetElementAt( int x, int y); const T& GetElementAt( int x, int y) const ; int GetHeight() const { return mHeight; } int GetWidth() const { return mWidth; } Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 14
  15. static const int kDefaultWidth = 10; static const int kDefaultHeight = 10; protected : void CopyFrom( const CGrid & src); template void CopyFrom( const CGrid & src); T m_Cells; int m_nWidth, m_nHeight; }; // ðnh ngh ĩa method template constructor sao chép template template CGrid ::CGrid( const CGrid & src) { CopyFrom(src); } o Nh n xét: Vì trong method template trên, ta s d ng ph ươ ng th c CopyFrom() , do v y, ta c ũng ph i template hố ph ươ ng th c này nh ư sau: // ðnh ngh ĩa method template CopyFrom() template template void CGrid ::CopyFrom( const CGrid & src) { int i, j; m_Width = src.GetWidth(); m_Height = src.GetHeight(); m_Cells = new T* [m_Width]; for (i = 0; i , trong khi con tr this đang tr đ n đi tưng thu c CGrid . o ðnh ngh ĩa cho method template operator = nh ư sau: // ðnh ngh ĩa method template operator = template template CGrid & CGrid :: operator =( const CGrid & rhs) { // Free the old memory. Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 15
  16. for (int i = 0; i class CGrid { public : CGrid() {} // Template hố constructor sao chép và operator = template CGrid( const CGrid & src); template CGrid & operator =( const CGrid & rhs); void GetElementAt( int x, int y, const T& inElem); T& GetElementAt( int x, int y); const T& GetElementAt( int x, int y) const ; int GetHeight() const { return HEIGHT; } int GetWidth() const { return WIDTH; } protected : // Template hố method CopyFrom //vì p.thuc này đưc dùng trong copy constructor ( đưc //template hố) template void CopyFrom( const CGrid & src); T m_Cells[WIDTH][HEIGHT]; }; // ðnh ngh ĩa method template constructor sao chép template template CGrid ::CGrid( const CGrid & src) { CopyFrom(src); } Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 16
  17. // ðnh ngh ĩa method template CopyFrom template template void CGrid ::CopyFrom( const CGrid & src) { int i, j; for (i = 0; i template CGrid & CGrid :: operator =( const CGrid & rhs) { CopyFrom(rhs); return (* this ); } Câu h i: Sinh viên hãy gi i thích s ho t đ ng c a đon ch ươ ng trình trên . 4.4. Function template Sinh viên t tìm hi u (trong đ thi cĩ ph n này) . Biên so n: ð ng Thanh D ũng, khoa CNTT - ðH SPKT TP.HCM 17