
آموزش سربارگذاری عملگرها (Operator overloading) در ++C
در این پست می خواهیم operator overloading (سربار گذاری عملگر ها ) را یاد بگیریم . اول بگذارید تعریفی از سربارگذاری عملگر ها ارایه کنیم .
فرض کنید شما کلاسی برای اعداد گویا نوشته اید ، اعداد گویا هم مانند مانند اعداد صحیح یک موجودیت ریاضی است و می توان آن ها را با هم جمع , ضرب و تفریق و … کرد .
حالا شما فرض کنید که دو شی از کلاس اعداد گویا به اسم های myobj1 و myobj2 ساخته اید و می خواهید آن ها را با هم جمع کنید، برای جمع کردن دو شی می توانید دو کار انجام دهید :
۱ – یک متد برای جمع کردن در کلاس بنویسید و یک اسم مثل sum برای متد انتخاب کنید و به این شکل استفاده کنید:
;(myobj3 = myobj2.sum( myobj1)
۲- از operator (عملگر) ” + ” استفاده کنید :
;myobj3 = myobj2 + myobj1
به حالت دوم operator overloading یا سربارگذاری عملگرها می گویند یعنی عملگر هایی مانند + ، =+ ، – ، =- ، / ، [ ] ، * ، >> ، << و …. را برای کلاستون تعریف کنید و از آن ها استفاده کنید .
از اونجایی که تقریبا تمام سربار گذاری ها شبیه هم اند در قالب یک مثال آن ها را توضیح می دهم .
فرض کنید کلاس test را به شکل زیر داریم :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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 یک واحد اضافه شود .
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 ++ است :
این عملگر هم تقریبا مانند عملگر قبلی است با این تفاوت که ابتدا از مقدار اولیه متغییر استفاده می شود و بعد از آن ++ می شود . راه تمام تعریف کردن آن نیز به صورت زیر است :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // 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 جمع شود . سربارگذاری عملگر + را به صورت زیر انجام می دهیم :
1 2 3 4 5 6 7 8 9 10 | // + 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 می شود. نحوه ی پیاده سازی عملگر > نیز مانند زیر است :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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 ;
و تعریف آن به صورت زیر است :
1 2 3 4 5 6 7 8 | // += overload void operator += (test x) { for(int i=0; i<20; i++) { element[i] += x.element[i]; } } |
و در نهایت صورت نهایی کلاس test را همراه main برنامه که شامل مثال هایی است را می بینید :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #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; } |
int & operator [] (int n)
سلام
ممنون از توضیحاتتون
من سوالم اینه که چرا&بعد int گذاشتید؟
سلام
برای اینکه یک رفرنس به خانه n برگردانده شود
اگر & نذاریم فقط مقدار آن خانه برگردانده می شود و ما نمی توانیم روی آن تغییری ایجاد کنیم
مثلا نمی تونمی بنویسیم
چون ما فقط مقدار آن خانه را برگردانده ایم ولی وقتی & می گذاریم یعنی یک رفرنس به آن خانه برگردانده ایم و می توانیم علاوه بر استفاده از مقدار آن خانه ، مقدارش را هم تغییر دهیم
سلام دوست من
اولا سپاسگذارم بابت مطالب خوبت.
دوما اینکه توی کامنت ها فیلد دوم باید بنویسی منتشر نخواهد شد ولی الان نوشته شده منتظر نخواهد شد.
سوما در مورد پلی مورفیسم هم بنویس.
چهارما توی این مطلبت برای اوور لود کردن ++ پریفیکس اشتباه نشده؟
فکر کنم یادت رفته که توی کلاس تست آرایه ها رو اعداد زوج قرار دادی. مثلا باید توی خونه ۲۰ آرایه عدد چهل و یک قرار بگیره نه ۲۱. هر چقدر فکر میکنم میبینم که نتیجه اشتباهه یا شایدم من اشتباه فکر میکنم.
کلاس تست که آرایه داره ، خونه های آرایه رو ۰،۲،۴،۶،………..،۴۰ پر کردی.
شاد باشی دوست من
سلام دوست عزیر تشکر از نظر عالیت ،چیز هایی که گفتی در روز های آینده انجام میدهم .
پلاس پلاس پرفیکس چک کردم درست بود ، شما چه اشکالی ازش دیده اید؟
اون سری که عدد چهل چاپ می کنه در کد
show
یکی به آخر است که روی آبجت دو است و ما آبجکت دو را دوبار قبلش پلاس پلاس کرده ایم پس عدد عدد چهل درسته
در آرایه بیست خانه داریم ولی آرایه از خانه ی صفر شماره گذاری می شه و خانه ی آخر شماره اش نوزده است نه بیست ، قبل از چاپ رویش چندتا از اپراتور ها را تست کرده ایم به همین خاطر مقادیرش فرق می کند.
سلام
ببین ما یه کلاس داریم به اسم تست. که یه آرایه خصوصی داره به اسم المنت که مقادیر المنت از ۰ تا ۴۰ هستش و دو تا دوتا بالا میره.۰،۲،۴،۶،۸،۱۰،۱۲،۱۴،۱۶،۱۸،۲۰،۲۲،۲۴،۲۶،۲۸،۳۰،۳۲،۳۴،۳۶،۳۸،۴۰ خوب تا اینجا درست؟
بعد تو اور لودینگ پریفیکس ++ شما یه آرایه المنت دیگه ایجاد کردی و با مقادیر ۱ تا بیست پرشون کردی. خوب؟
بعد این مقادیر رو توی المنت کلاس تست قرار دادی. درسته؟
حالا المنت کلاس تستت مقادیر یک تا بیست رو گرفته. درسته؟ در حالیکه باید مقادیر یک تا۴۱ رو بگیره. درسته؟
حالا متوجه منظورم شدی؟ در ضمن در صورت نهایی کلاس تستت هم پریفیکس ++ رو قرار ندادی.
شاد باشی
پاسخ ، اولین سوالت اشتباه است زیرا را آرایه المنت ۲۰ عضو دارد، و در سی پلاس پلاس شماره گذاری آرایه از صفر شروع می شود در نتیجه ارایه ما خانه هایش از صفر تا نوزده است و در هر خانه دوبرابر شماره خانه درش ریخته شده خانه ی صفر مقدار صفر ،خانه ی یک مقدار دو و همین طور تا خانه ی نوزده که مقدار سی و هشت در آن است ، یعنی خانه ی آخر مقدار سی و هشت دارد اگر به عدادی که نوشتی توجه کنی می بینی که بیست و یک عدد نوشتی نه بیست عدد!
خوب قبول. پس بعد از اعمال ++ پریفیکس باید از یک تا سی و نه بشه. درسته؟
آیا اور لودت این نتیجه رو میده؟
خوب درسته باید سی و نه بشه ولی من قبل از اینکه چاپش کنم ++ پوستفیکس هم روش انجام دادم
راستی پلی مورفیسم هم یادت نره دوست من.
حتما می نویسم
سلام
خسته نباشید
یه سوال : چجوری میشه زمان جاری سیستم رو در ++C خوند و مقدارش رو توی یه متغیر string ریخت ؟
ممنون میشم راهنمایی کنید
سلام من ترم ۲ نرم افزارم…به برنامه نویسی علاقه داشتم ولی تاقبل ازورود به دانشگاه عملا”چیزی ازش نمیدونستم…در حال حاضر هم در حد دو ترم نرم افزار خوندن از برنامه نویسی میدونم… خیلی علاقه مند به یادگیریم ولی نمیدونم باید چیکار کنم… پیشنهادتون در حال حاضر برای من چیه؟؟؟ممنون میشم راهنماییم کنید…
از اونجایی که ترم ۲ هستی بهترین کار اینه که این تابستون یک زبان برنامه نویسی خوب مثل سی پلاس پلاس رو کارکنی و بهش کاملا مسلط بشوید ! و بهترین روش هم یادگیری به همراه انجام پروژه است ، یعنی شما یک مطلب مثل کتابخانه اس تی ال سی پلاس پلاس می خونی و بعد یک پروژه که از اس تی ال استفاده می کند برای خودت طرح می کنی و پروژه را انجام می دهی!
سلام آقای دلیرانی ….
واقعا خسته نباشی ..خیلی توضیحات مفید وقبراقی بود..
امیدوارم راجع به polymorphism هم همینطور مطالب ساده و مفید رو قرار بدید….
راستی تو یوتیب یه کانالی هس به اسم bucky که خیلی ساده و مفید ++cرو آموزش میده گفتم شاید به دردتون بخوره…
سپاسگزارم..
تشکر بخاطر لطفتونه و همین طور معرفی اون کانال