OPERATOR OVERLOADING(Перегрузка операторов)


Operator overloading(Перегрузка операторов)

Operator overloading နွင့္ fuction overloading တို႕၏ ၿခားနားခ်က္သည္ operator overloading သည္ class နွင့္အၿမဲတမ္းဆက္စပ္ေနေလ့ရွိသည္။မူရင္း တန္ဖိုးတစ္ခုမွေန၍ operator overload ၿပဳလုပ္လွ်င္ ၎၏ original တန္ဖိုးသည္ ဆံုးရွံဳးေပ်ာက္ကြယ္သြားလိမ့္မည္ မဟုတ္ေပ။သို႕ေသာ္ ၎သည္ ေၿပာင္းလဲမွဳ႕အေၿခအေနတစ္ရပ္ အသစ္တစ္ခု ထပ္မံၿဖစ္ေပၚလာလိမ့္မည္ၿဖစ္သည္။
Operator overloading အား operator_function(оператор-функция)အားၿဖင့္ define ၿပဳလုပ္ရမည္ၿဖစ္သည္။ ၎ function သည္ class ၏ member တစ္ခုၿဖစ္နိဳင္သကဲ့သို႕ friend function လည္းၿဖစ္နိဳင္သည္။
type classname :: operator # (list)
{        action_performed
}
သည္တြင္ # သေကၤတေနရာတြင္ overloaded operator တစ္ခုခုအား အသံုးၿပဳရမည္ၿဖစ္သည္။ ေအာက္ေဖာ္ၿပပါ overloaded operator မ်ားအား အစားထိုးသံုးစြဲနိဳင္သည္။
+  -  *  /  %  ^  &  |  ~  !  !=  ==  <  >  <=  >=  <<  >>  &&  ||  ++  --  =  +=  -=  *=  /=  %=  ^=  &=  |=  <<=  >>=  ->  ->*  ,  []  ()  new  delete.

Operator overloading တြင္ ကန္႕သန္႕ခ်က္ရွိေသာ အေၿခအေနတို႕မွာ ေအာက္ပါအတိုင္းၿဖစ္သည္။  
  • operators can not be overloaded:. . * ::?: Sizeof preprocessor operators;
  • you can not change the priority of operators;
  • can not change the number of operands of the operator with respect to its original state;
  • You can not create new transactions, you can only overload the already existing ones;
  • operator functions can not have parameters passed by default. 

Function operation မ်ားသည္ single(unary) နွင့္ double(binary) နွစ္ခုစလံုးၿဖစ္နိဳင္သည္unary နွင့္ binary – operations မ်ားတြင္ overloaded အသံုးၿပဳပံုၿခင္း တူညီလိမ့္မည္မဟုတ္ေပ။သို႕ေသာ္လည္း operation ၿပဳလုပ္ပံုၿခင္းေတာ့္ အတူူတူပင္ၿဖစ္သည္။ဆိုလိုသည္မွာ execution ၿပဳလုပ္လွ်င္ “left to right” ဆိုလွ်င္ operation နွစ္ခုစလံုးသည္ စတင္ execute ၿပဳလုပ္လွ်င္ left ဘက္မွေန၍စတင္ၿပဳလုပ္လိမ့္မည္ ၿဖစ္သည္။ထို႕အတူ “right to left” ဆိုလွ်င္လည္း right ဘက္မွေန၍ စတင္အလုပ္လုပ္လိမ့္မည္ၿဖစ္သည္။
  
Overloading unary operators
Unary operator မ်ားတြင္ operand တစ္ခုသာ တည္ရွိမည္ၿဖစ္သည္။ထို႕ေၾကာင့္ class ၏ unary operator မ်ားသည္ non-static member_function ၿဖစ္ၿပီး argument ပါ၀င္လိမ့္မည္မဟုတ္ေပ။သို႕ေသာ္ friend_function တြင္ argument တစ္ခုပါ၀င္လိမ့္မည္ၿဖစ္သည္။ထို argument သည္ class ၏ object သို႕မဟုတ္ class ၏ object အားညြန္းေသာ reference တစ္ခုခုၿဖစ္ရမည္ၿဖစ္သည္။
Function_element မ်ား သည္ class ၏ non-static element မ်ားဆီသို႕ access ၿပဳလုပ္ရန္မလိုအပ္လွ်င္ static အၿဖစ္ေၾကၿငာရမည္ၿဖစ္သည္။non_static နွင့္ static တို႕၏ အဓိကကြဲၿပားခ်က္သည္ static function_element သည္ this_pointer မပိုင္ဆိုင္ေပ။
ပံုမွန္အားၿဖင့္ class ၏ object တိုင္းသည္ class ၏ data_element မ်ားအားလံုးတို႕၏ copy မ်ားကိုယ္ပိုင္ရွိတက္ ၾကသည္။သို႕ေသာ္ တိက်စြာထပ္မံဆိုရလွ်င္  တစ္ခ်ိဳ႕ေသာ data_element မ်ား သည္ class ၏ object အားလံုးအတြက္ copy တစ္ခုသာတည္ရွိသည္။(ဆိုလိုသည္မွာ object အားလံုးအတြက္ အခ်ိဳ႕ data မ်ားသည္ copy တစ္ခုသာတည္ရွိၿပီး အမ်ားပိုင္သကဲ့သို႕ၿဖစ္ေနတက္သည္)။ထိုရည္ရြယ္ခ်က္ၿဖင့္ class တစ္ခုလံုး၏ information အတြက္ static_data မ်ားအား အသံုးၿပဳၿခင္းၿဖစ္သည္။ထို static အား ေၾကၿငာအသံုးၿပဳရန္အတြက္ static ဆိုေသာ စာသားအားအသံုးၿပဳရသည္ၿဖစ္သည္။(static အေၾကာင္းအား ေဖာ္ၿပခဲ့ၿပီးၿဖစ္)။

Example. Overload "-" as a unary version.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         twins &operator -();
                         void show_tw()  {  cout << t1 << "  " << t2 <<endl;  }
                   };
twins &twins :: operator -()
{  t1 = -t1;
    t2 = -t2;
    return *this;
}
int _tmain(int argc, _TCHAR* argv[])
{  twins ob1, ob2(17, -19);
   ob1 = -ob2;
   ob1.show_tw();
   ob2.show_tw();
   _getch();
          return 0;
}


Example . Overloading the increment operator (+ +) in the prefix and postfix notation.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         void get_tw(int &a, int &b)  {  a = t1; b = t2;  }
                         twins& operator ++();
                         twins& operator ++(int);
};
twins &twins :: operator ++()
{  t1++;
    t2++;
    return *this;
}
twins &twins :: operator ++(int)
{  ++t1;
    ++t2;
    return *this;
}
int _tmain(int argc, _TCHAR* argv[])
{ twins ob, ob1(10, 15), ob2(17, 19);
   int m, k;
   ob = ob1++;
   ob1.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 11 16
   ob.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 11 16
   ob = ++ob2;
   ob2.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 18 20
   ob.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 18 20
   _getch();
          return 0;
}
  
Overloading binary operators
Class တြင္ binary operator မ်ားသည္ non-static function_element အၿဖစ္ overloaded ၿပဳလုပ္သည္။ ထိုသို႕ ၿပဳလုပ္ရာတြင္ argument တစ္ခုတည္း သို႕မဟုတ္ friend_function ဆိုလွ်င္ argument နွစ္ခုၿဖင့္ အလုပ္လုပ္ေလ့ရွိသည္။ထို argument မ်ားအနက္မွ တစ္ခုသည္ သည္ class ၏ object သို႕မဟုတ္ class ၏ object အားညြန္းေသာ reference တစ္ခုခုၿဖစ္ရမည္ၿဖစ္သည္။

Example. Overload operators +, - and =.
#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         void get_tw(int &a, int &b)  {  a = t1; b = t2;  }
                         twins operator +(twins o2);
                         twins operator -(twins o2);
                         twins& operator =(twins o2);
                   };
twins twins :: operator +(twins o2)
{   twins temp;
          temp.t1 = t1 + o2.t1;
    temp.t2 = t2 + o2.t2;
    return temp;
}
twins twins :: operator -(twins o2)
{  twins temp;
    temp.t1 = t1 - o2.t1;
    temp.t2 = t2 - o2.t2;
    return temp;
}
twins &twins :: operator =(twins o2)
{  twins temp;
    t1 = o2.t1;
    t2 = o2.t2;
    return *this;
}
int _tmain(int argc, _TCHAR* argv[])
{ twins ob, ob1(10, 15), ob2(17, 19),ob3;
   int m, k;
   ob3 = ob1 + ob2;
   ob3.get_tw(m, k);
   cout << m << ' ' << k << endl;
   ob3 = ob1 - ob2;
   ob3.get_tw(m, k);
   cout << m << ' ' << k << endl;
   ob3 = ob1;
   ob3.get_tw(m, k);
   cout << m << ' ' << k << endl;
   _getch();
          return 0;
}
Operator + နွင့္ - အား overload ၿပဳလုပ္ေသာအခါ ၎ overloaded operator အတြင္းတြင္ temp ဟူေသာ ယာယီ object အားအသံုးၿပဳထားသည္ကိုေတြ႕ၿမင္ရမည္ ၿဖစ္ၿပီး ၎ သည္ value အား return ၿပန္ရန္အတြက္ ၿဖစ္သည္။

Use reference overload operators
Operator function တြင္ reference အားအသံုးၿပဳနိဳင္သည္ ၿဖစ္သည္။
Example. overload + for class twins using references.
twins twins :: operator + (twins &o2)
{        twins temp;
temp.t1 = t1 + o2.t1;
temp.t2 = t2 + o2.t2;
return temp;
}
Reference အား argument အၿဖစ္အသံုးၿပဳၿခင္းအားၿဖင့္ program code မ်ား ပိုမိုေကာင္းမြန္ေစၿပီး by value နည္းအားၿဖင့္ passing ၿပဳလုပ္ၿခင္းထက္ပိုမို၍ memory အသံုးၿပဳရာတြင္ ထိေရာက္မွဳ႕ရွိၿပီး ပိုမိုၿမန္ဆန္ေစသည္ ၿဖစ္သည္။
သို႕ေသာ္လည္း return value သည္ reference(link) မၿဖစ္နိဳင္ေပ။အထက္ေဖာ္ၿပပါ ပုစၦာတြင္ temporary variable ၿဖစ္ေသာ temp သည္ reference မဟုတ္ပဲ reference ဆီသို႕ point ၿပဳလုပ္ေသာ variable တစ္ခုသာ ၿဖစ္သည္။function သည္ return ၿပဳလုပ္ၿပီးေသာ အခါ ထို variable အားဖ်က္စီးပစ္လိမ့္မည္ ၿဖစ္သည္။ထို႕ေၾကာင့္ ကၽြနဳပ္တို႕သည္ ထို ယာယီ variable မွ point ၿပဳလုပ္ထားေသာ reference(link) ကိုသာလွ်င္ ရရွိလိမ့္မည္ၿဖစ္သည္။
မည္သည့္အခါမွ reference( pointer သည္လည္းတို႕အတူပင္) အား local variable နွင့္ အၿခားေသာ temporary object မ်ားတြင္ တည္ေဆာက္ၿခင္း(ေၾကၿငာၿခင္း)မၿပဳသင့္ေပ။

Overload relational operators and logical operators
Relational operator နွင့္ logical operator တို႕အား overloaded ၿပဳလုပ္ေသာအခါ class ၏ object မ်ားသည္ return ၿပန္လိမ့္မည္မဟုတ္ေပ။ integer variable ၿဖစ္ေသာ true (or) false နွစ္ခုသာလွ်င္ return ၿပန္လိမ့္မည္ၿဖစ္သည္။

Example. Overloading the  ==, && and. | |.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         void get_tw(int &a, int &b)  {  a = t1; b = t2;  }
                         int operator ==(twins o2);
                         int operator &&(twins o2);
                         int operator ||(twins o2);
                   };
int twins :: operator ==(twins o2)
{  if ((t1 == o2.t1) && (t2 == o2.t2))    return 1;
       else   return 0;
}
int twins :: operator &&(twins o2)
{  return ((t1 && o2.t1) && (t2 && o2.t2));  }
int twins :: operator ||(twins o2)
{  return ((t1 || o2.t1) && (t2 || o2.t2));  }
int _tmain(int argc, _TCHAR* argv[])
{ twins ob1(10, 15), ob2(17, 19), ob3(0, 0), ob4(10,15), ob5(0, 0);
   if (ob1 == ob2) cout << "Objects are equal" << endl;
      else cout << "Objects are not equal" << endl;
   if (ob1 == ob4) cout << "Objects are equal" << endl;
      else cout << "Objects are not equal" << endl;
   if (ob1 && ob2) cout << "True" << endl;
      else cout << "False" << endl;
   if (ob1 && ob3) cout << "True" << endl;
      else cout << "False" << endl;
   if (ob1 || ob2) cout << "True" << endl;
      else cout << "False" << endl;
   if (ob5 || ob3) cout << "True" << endl;           
      else cout << "False" << endl;
   _getch();
          return 0;
}

Indexing operator overloading
Array indexing operator သည္လည္း class ၏ data_element မ်ားဆီသို႕ access ၿပဳလုပ္ရန္အတြက္ overloaded ၿပဳလုပ္နိဳင္သည္ၿဖစ္သည္။ထို႕ထက္ပို၍ ထို data မ်ားသည္ array ပံုစံမဟုတ္သည့္ တိုင္ေအာင္ access ၿပဳလုပ္နိဳင္သည္ၿဖစ္သည္။

Example 20.7. Suppose private data-elements of the class are some individual variables that have the same type, but not into the array. overload the index so that you can arrange access to them access to the same array.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class NotArr {  int a0;
                         int a1;
                         int a2;
                         int a3;
                         int a4;
                         int a5;
                       public:
                         NotArr (int v0, int v1, int v2, int v3, int v4, int v5)
                              {   a0 = v0;   a1 = v1;   a2 = v2;
                                   a3 = v3;   a4 = v4;   a5 = v5;
                              }
                         int get_a(unsigned i);
                         int operator [](unsigned i);
                     };
int _tmain(int argc, _TCHAR* argv[])
{  NotArr na(1, 2, 3, 4, 5, 6);
    for (int ind = 0; ind < 6; ind++)
         cout << na[ind] << ' ';
    cout <<endl;
   _getch();
          return 0;
}
int NotArr :: get_a(unsigned i)
{  switch (i)
{  case 0: return a0; // оператор break здесь не нужен, так как выход  //происходит
                                      // по оператору return и до break дело просто не дойдет
           case 1: return a1;
           case 2: return a2;
           case 3: return a3;
           case 4: return a4;
           case 5: return a5;
           defaultreturn a0;
       }
}
int NotArr :: operator[](unsigned i)
{  return get_a(i);
}

Overloaded assignment operator
Bitwise copy ကူးၿခင္းအားၿဖင့္ assignment operator မ်ားအား overload ၿပဳလုပ္နိဳင္သည္။
Example.            
#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <string.h>
using namespace std;
class  MyStr{  char *sPtr;
                         int length;
                       public:
                         MyStr(char *s);
                ~MyStr() {  cout << "Освобождаем память" << endl;
                                     delete []sPtr;
                                 }
                  char *get() {  return sPtr;  }
                  MyStr &operator = (MyStr &ob);
            };

MyStr:: MyStr(char *s)
{  int len;
    len = strlen(s);
    sPtr = new char[len + 1];
    if (!sPtr)  {   cout << "Ошибка выделения памяти" << endl;
                         exit(1);
                    }
    length = len;
    strcpy(sPtr, s);
}
MyStr &MyStr:: operator = (MyStr &ob)
{   if (length < ob.length)         // необходима дополнительная память
       {  delete []sPtr;
           sPtr = new char[ob.length + 1];
           if (!sPtr)  {   cout << "Ошибка выделения памяти" << endl;
                                exit(1);
                           }
       }
     length = ob.length;
     strcpy(sPtr, ob.sPtr);
     return *this;
}
int _tmain(int argc, _TCHAR* argv[])
{  MyStr a("Hallo"), b("Good morning");
   cout << a.get() << endl;
   cout << b.get() << endl;
   a = b;
   cout << a.get() << endl;
   cout << b.get() << endl;
   _getch();
          return 0;
}
Assignment operator အား overloading ၿပဳလုပ္ေသာအခါ sPtr အားၿဖင့္ bitwise copying ၿပဳလုပ္သည္ကို ေတြ႕ၿမင္နိဳင္သည္။program အား process ၿပဳလုပ္ေနေသာအခါ ဘယ္ဘက္ရွိ assign ၿပဳလုပ္မည့္ string object အတြက္ memory အၿပည့္အ၀ရွိမရွိ စစ္ေဆးၿပီးမွသာ ၿပဳလုပ္ေၾကာင္းေတြ႕ၿမင္နိဳင္သည္။အကယ္၍ memory မလံုေလာက္လွ်င္ memory အားပယ္ဖ်က္လိုက္ၿပီး ေနာက္ထပ္အသစ္ထပ္မံယူသည္ကို ေတြ႕ၿမင္နိဳင္သည္။ထို႕ေနာက္တြင္ ထို memory ဆီသို႕ string အား copy ကူးယူၿပီး ၎ ၏ length သည္လည္း အသစ္ကူးယူလိုက္သည့္ string_object ၏ length နွင့္တူညီလိုက္သည္ကို ေတြ႕ၿမင္ရမည္ၿဖစ္သည္။

Use of friend operator_function
Friend operator_function နွင့္အတူ operator overloading ၿပဳလုပ္ေသာအခါ this_pointer အား အသံုးၿပဳနိဳင္မည္မဟုတ္ေပ။ထို႕ေၾကာင့္ friend_function တြင္ binary operator အား overload ၿပဳလုပ္လွ်င္ operand 2 ခုအား အသံုးၿပဳမည္ရမည္ၿဖစ္ၿပီး unary operator အား overload ၿပဳလုပ္ပါက operand 1 ခု အသံုးၿပဳမည္ၿဖစ္သည္။
Friend operator function အား overlaod ၿပဳလုပ္ၿခင္းသည္ function_element မ်ားအား overload ၿပဳလုပ္ၿခင္းနွင့္အတူတူပင္ၿဖစ္သည္။သို႕ေသာ္ ေအာက္ေဖာ္ၿပပါ ကန္႕သတ္ခ်က္နွစ္ခုရွိသည္ ၿဖစ္သည္။
friend function သည္ assignment operator အား overload မၿပဳလုပ္နိဳင္ေပ။
friend function-operator အား အသံုးၿပဳလွ်င္ operation မ်ားတြင္ object မ်ားအား built-in(inline) data_type အားအသံုးၿပဳနိဳင္သည္။ထို inline data_type အား operator မွ ဘယ္ဘက္တြင္ ထားရွိနိဳင္သည္ ၿဖစ္သည္။


Example. + operator overloading for the case of friend operator-function.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         void get_tw(int &a, int &b)  {  a = t1; b = t2;  }
                         friend twins operator +( twins o1, twins o2);
                         friend twins operator +( twins o1, int i);
                         friend twins operator +( int i, twins o1);                  
                   };
twins operator +( twins o1, twins o2)
{  twins temp;
    temp.t1 = o1.t1 + o2.t1;
    temp.t2 = o1.t2 + o2.t2;
    return temp;
}
twins operator +( twins o1, int i)
{  twins temp;
    temp.t1 = o1.t1 + i;
    temp.t2 = o1.t2 + i;
    return temp;
}
twins operator +( int i, twins o1)                  
{  twins temp;
    temp.t1 = o1.t1 + i;
    temp.t2 = o1.t2 + i;
    return temp;
}
int _tmain(int argc, _TCHAR* argv[])
{  twins ob1(10, 15), ob2(17, 19), ob3, ob4;
   int m, k;
   ob3 = ob1 + ob2;
   ob3.get_tw(m, k);
   cout << m << ' ' << k << endl;
   ob3 = ob1 + 100;
   ob3.get_tw(m, k);
   cout << m << ' ' << k << endl;
   ob4 = 100 + ob2;
   ob4.get_tw(m, k);
   cout << m << ' ' << k << endl;
   _getch();
          return 0;
}

Friend operator_function အား unary operator မ်ားၿဖစ္ၾကေသာ ++ နွင့္ - - အတြက္ အသံုးၿပဳေသာအခါ operand မ်ားသည္ ဖန္ရွင္ဆီသို႕ reference(link) parameter အၿဖစ္ pass ၿပဳလုပ္လိမ့္မည္ၿဖစ္ၿပီး friend operator-function ဆီသို႕ this_pointer သည္ passing ၿပဳလုပ္လိမ့္မည္မဟုတ္ေပ။increment(++) နွင့္ decrement(--) operators မ်ားတြင္ operand သည္ တန္ဖိုး ေၿပာင္းလဲလိမ့္မည္ၿဖစ္သည္။

Example. Overloading the increment operator (+ +) using an operator-friendly features.

#include "stdafx.h"
#include <iostream>
#include <conio.h>
using namespace std;
class twins {    int t1, t2;
                     public:
                         twins()  {  t1 = 0;  t2 = 0;  }
                         twins(int a, int b)  {  t1 = a;  t2 = b;  }
                         void get_tw(int &a, int &b)  {  a = t1; b = t2;  }
                         friend twins operator ++( twins &o);
                  };

twins operator ++( twins &o)
{  o.t1++;
    o.t2++;
    return o;
}

int _tmain(int argc, _TCHAR* argv[])
{  twins ob, ob1(10, 15), ob2(17, 19);
   int m, k;
   ob = ob1++;
   ob1.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 11 16
   ob.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 11 16
   ob2++;
   ob2.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 18 20
   ob.get_tw(m, k);
   cout << m << ' ' << k << endl;    // 18 20
   _getch();
          return 0;
}


                                                                           translated by zmk@miet51


No comments:

Post a Comment