در این پست می خواهیم operator overloading (سربار گذاری عملگر ها ) را یاد بگیریم . اول بگذارید تعریفی از سربارگذاری عملگر ها ارایه کنیم .
فرض کنید شما کلاسی برای اعداد گویا نوشته اید ، اعداد گویا هم مانند مانند اعداد صحیح یک موجودیت ریاضی است و می توان آن ها را با هم جمع , ضرب و تفریق و … کرد .
حالا شما فرض کنید که دو شی از کلاس اعداد گویا به اسم های myobj1 و myobj2 ساخته اید و می خواهید آن ها را با هم جمع کنید، برای جمع کردن دو شی می توانید دو کار انجام دهید :
۱ – یک متد برای جمع کردن در کلاس بنویسید و یک اسم مثل sum برای متد انتخاب کنید و به این شکل استفاده کنید:
;(myobj3 = myobj2.sum( myobj1)
2- از operator (عملگر) ” + ” استفاده کنید :
;myobj3 = myobj2 + myobj1
به حالت دوم operator overloading یا سربارگذاری عملگرها می گویند یعنی عملگر هایی مانند + ، =+ ، – ، =- ، / ، [ ] ، * ، >> ، << و …. را برای کلاستون تعریف کنید و از آن ها استفاده کنید .
از اونجایی که تقریبا تمام سربار گذاری ها شبیه هم اند در قالب یک مثال آن ها را توضیح می دهم .
فرض کنید کلاس test را به شکل زیر داریم :
class test { private: int element[20]; public: //constructor test() { for(int i=0;i<20;i++) { element[i] = i*2; } } // [] overload // prefix ++overload // postfix ++overload // + overload // < overload // += overload //show array of int };
همین طور که می بینید در کلاس Test یک آرایه بیست عضوی به نام element به عنوان یک عضو از کلاس را داریم . همین طور که می بینید درون کلاس یک سری کامنت هست که قرار است همه ی آن ها را به ترتیب سربارگذاری عملگر ها یا operator overloading کنیم.
سربارگذاری عملگر [ ] :
فرض کنید شی myobj را از کلاس test به صورت زیر تعریف کرده ایم :
test myobj;
بعد از ساختن شی myobj سازنده (constructor) تابع اجرا می شود و آرایه element شی myobj را با اعداد ۰و۲و۴و … و ۴۰ پر می کند.حالا فرض کنید که می خواهید خانه
پنجم آرایه را چاپ کنید چه می کنید ؟
از اون جایی که که آرایه element یک خصوصیت private است نمی توانید بگویید :
cout << myobj.element[4] ;
کاری که می ماند نوشتن یک تابع برای کلاس است.توابع کلاس به اعضای private دسترسی دارند و می توانید به نوشتن یک تابع عضو مورد نظر خود را از آرایه برگردانید , در زیر من یک
تابع به اسم get_element تعریف کردم که یک refrence از خانه مورد نظرم از آرایه برمی گرداند.
int & get_element( int n ) //n is n-th place of array
{
return( element[n]);
}
و طرز استفاده از آن به صورت به صورت زیر است :
cout << myobj.get_element(4);
ولی راه حل زیبا تر و خوانا تر سربارگذاری عملگرها چی می گوید؟
شما برای دسترسی به یک آرایه عادی از اعداد صحیح چه می کنید ؟ بدون شک می نویسید :
int A[10];
cout << A[3] ;
ما نیز می توانیم با سربار گذاری عملگر [ ] به اعضای آرایه element شی myobj به صورت زیر دسترسی پیدا کنیم:
cout << myobj[4] ;
برای overload عملگر [ ] به صورت زیر عمل می کنیم :
int & operator [](int n)
{
return element[n];
}
عملگر بعدی که می خواهیم سربارگذاری کنیم عملگر ++ prefix است :
اگر یادتان باشد وقتی برای یک متغییر صحیحی مانند b ما می نوشتیم b++ آنگاه به مقدار b یک واحد اضافه می شد . حالا می می خواهیم اپراتور ++ پیشوندی را طوری اورلود کنیم به طوری که هر وقت روی یک شی از کلاس test عملگر ++ را به کارببریم به تمام اعضای آرایه element یک واحد اضافه شود .
test operator ++() { test y; for(int i = 0; i<20;i++) { ++element[i]; } for(int i = 0; i<20;i++) { y.element[i] = element[i]; } return y; }
و طرز استفاده از آن به صورت زیر است :
test myobj1 = ++ myobj;
یا
++myobj;
اپراتور بعدی که می خواهیم overload کنیم عملگر postfix ++ است :
این عملگر هم تقریبا مانند عملگر قبلی است با این تفاوت که ابتدا از مقدار اولیه متغییر استفاده می شود و بعد از آن ++ می شود . راه تمام تعریف کردن آن نیز به صورت زیر است :
// postfix ++overload test operator ++(int) { test y; for(int i = 0; i<20;i++) { y.element[i] = element[i]; } for(int i = 0; i<20;i++) { ++element[i]; } return y; }
شاید از خود بپرسید که چرا درون پرانتز کلمه int را گذاشتیم ! دلیل آن این است که می خواهیم به کامپایلر بگوییم که این ++ از نوع postfix است.
و شکل استفاده از آن هم به صورت زیر است:
test myobj1 = myobj ++;
یا
myobj ++;
اپراتور بعدی که می خواهیم سربارگذاری کنیم اپراتور + است :
عملگر + همان عملگر جمع است که برای اعداد صحیح به صورت A+B * c +d استفاده می کردیم.حالا می خواهیم این عملگر را برای کلاس test سربارگذاری کنیم .
بطوری که : هر وقت شی myobj را با شی myobj1 به صورت زیر با هم جمع کردیم
myobj + myobj1
تک تک اعضای آرایه element شی myobj با اعضای نظیر خود در آرایه شی myobj1 جمع شود . سربارگذاری عملگر + را به صورت زیر انجام می دهیم :
// + overload test operator + (test x) { test y; for(int i=0; i<20; i++) { y.element[i] = element[i] + x.element[i]; } return y; }
و طریقه استفاده از آن به صورت زیر است :
myobj2 = myobj + myobj1;
اپراتور بعدی که سربارگذاری می کنیم اپراتور > (کوچک تری ) است.
ما اپراتور کوچک تری را به صورتی پیاده سازی می کنیم که اگر مجموع اعضای آرایه element شی اولی از مجموع اعضای آرایه element دومی کوچک تر بود آنگاه رابطه درست است و مقدار شرط true می شود در غیر این صورت مقدار شرط false می شود. نحوه ی پیاده سازی عملگر > نیز مانند زیر است :
overloading" >// < overload bool operator < (test x) { int sum1; int sum2; for(int i=0; i<20; i++) { sum1 = element[i]; sum2 = x.element[i]; } if(sum1<sum2) { return true; } else { return false; } }
یک مثال از نحوه استفاده :
if( myobj < myobj1)
{
cout << “myobj is smaller than myobj1″;
}
اپراتور بعدی اپراتور =+ است :
این اپراتور که به صورت زیر استفاده می شود
myobj1 += myobj;
در واقع به شکل زیر است :
myobj1 = myobj1 + myobj ;
و تعریف آن به صورت زیر است :
// += overload void operator += (test x) { for(int i=0; i<20; i++) { element[i] += x.element[i]; } }
و در نهایت صورت نهایی کلاس test را همراه main برنامه که شامل مثال هایی است را می بینید :
#include <iostream> using namespace std; //class test class test { private: int element[20]; public: //constructor test() { for(int i=0;i<20;i++) { element[i] = i*2; } } // [] overload int & operator [] (int n) { return element[n]; } // prefix ++overload test operator ++() { test y; for(int i = 0; i<20;i++) { ++element[i]; } for(int i = 0; i<20;i++) { y.element[i] = element[i]; } return y; } // postfix ++overload test operator ++(int) { test y; for(int i = 0; i<20;i++) { y.element[i] = element[i]; } for(int i = 0; i<20;i++) { ++element[i]; } return y; } // + overload test operator + (test x) { test y; for(int i=0; i<20; i++) { y.element[i] = element[i] + x.element[i]; } return y; } // < overload bool operator < (test x) { int sum1; int sum2; for(int i=0; i<20; i++) { sum1 = element[i]; sum2 = x.element[i]; } if(sum1<sum2) { return true; } else { return false; } } // += overload void operator += (test x) { for(int i=0; i<20; i++) { element[i] += x.element[i]; } } //show array of int void show() { for(int i=0;i<20;i++) { cout<<element[i]<<endl; } } }; //mmain int main() { test myobject1; test myobject2; test myobject3; // + overload example cout<<"------------------------"<<endl; myobject3 = myobject1 + myobject2; myobject3.show(); // < overload example cout<<"------------------------"<<endl; if(myobject3 < myobject1) { cout<<"My object3 smaller than Myobject1"<<endl; } else { cout<<"My object1 smaller than Myobject3"<<endl; } // += overload example cout<<"------------------------"<<endl; myobject3 += myobject1; myobject3.show(); // ++ prefix example cout<<"------------------------"<<endl; myobject1 = ++myobject2; myobject1.show(); myobject2.show(); // ++ prefix example cout<<"------------------------"<<endl; myobject1 = myobject2++; myobject1.show(); myobject2.show(); //covert test2 object to test object example cout<<"------------------------"<<endl; cout<<myobject3[6]<<endl; //open-mind.ir return 0; }