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;
default: return 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