در دو حالت کلی مساله رو در نظر میگیریم. پیادهسازی به صورت تابع عضو و پیادهسازی به صورت تابع دوست.
پیادهسازی به صورت تابع عضو
در این حالت عملگر یکانی به صورت [const] T operaotr+() [const]
(یا [const] T operator-() [const]
) سربارگذاری میشه. T
میتونه هر نوع دادهای باشه و حتی میتونه void
باشه.
const
قبل از امضای تابع مشخص میکنه که نوع بازگشتی به صورت const
برگردونده بشه یا نه.
const
پس از پرانتز آرگومانها هم همون طور که مشخصه معلوم میکنه که تابع شی فراخواننده رو تغییر میده یا نه.
یعنی همهی امضاهای زیر درست هستند
void operator+() const;
void operator+();
T operator+();
T operator+() const;
const T operator+();
const T operator+() const;
T& operator();
const T& operator();
T& operator+() const;
const T& operator+() const;
T* operator+();
const T* operator();
T* operator+() const;
const T* operator+() const;
دو امضای زیر در صورتی که نیاز به برگشت this
یا *this
از تابع باشه درست نیستند
T& operator+() const;
T* operator+() const;
برای این که یک تابع عضو که قراره const
باشه نمیتونه اشارهگری به خود شی برگردونه. مخالف با const
اعلان کردن تابع هست. یعنی کد زیر اشتباهه
class C
{
private:
...
public:
C& operator+() const
{
...
return *this;
}
};
نکته این که T
لازم نیست از نوع شی فراخواننده باشه. هر نوع دلخواهی میتونه باشه. مثلاً کد زیر درسته
class C
{
private:
...
public:
int operator+() const
{
...
return 0;
}
};
پیادهسازی به صورت تابع دوست
در این حالت const
پس از پرانتز آرگومانها مفهوم پیدا نمیکنه. امضاهای ممکن به شکل [const] T2 operator+([const] T)
هستند.
T
شیای از کلاس، یا ارجاع به شیای از کلاس هست و T2
یک نوع دادهی دلخواه که میتونه void
یا هر نوع دادهی دلخواه دیگهای باشه.
void operator+(T obj);
void operator+(const T obj);
void operator+(T &obj);
void operator+(const T &obj);
T operator+(T obj);
T operator+(const T obj);
T operator+(T &obj);
T operator+(const T &obj);
T& operator+(T obj);
T& operator+(const T obj);
T& operator+(T &obj);
T& operator+(const T &obj);
T* operator+(T obj);
T* operator+(const T obj);
T* operator+(T &obj);
T* operator+(const T &obj);
const T& operator+(T obj);
const T& operator+(const T obj);
const T& operator+(T &obj);
const T& operator+(const T &obj);
const T* operator+(T obj);
const T* operator+(const T obj);
const T* operator+(T &obj);
const T* operator+(const T &obj);
در میان این امضاها هم مواردی هستند که در صورت برگردوندن اشارهگر یا آدرس شی فراخواننده نمیتونن استفاده بشن. این موارد اونهایی هستند که شی رو به صورت const
دریافت میکنن و به صورت غیر const
برمیگردونن. یعنی موارد زیر
T& operator+(const T obj);
T& operator+(const T &obj);
T* operator+(const T obj);
T* operator+(const T &obj);
بهترین انتخاب بستگی به مورد استفاده هر کدوم از این امضاها میتونن استفاده شن. اما به طور کلی اگه خود شی فراخواننده در انتها برگردونده میشه بهتره از یکی از شکلهایی زیر استفاده کنیم
const T& operator+(); // عضو
T& operator+(); // عضو
const T& operator+(T& obj); // دوست
T& operator+(T& obj); // دوست
هیچ پژوهش انسانی نمیتواند ادعای علمی بودن داشته باشد، مگر اینکه از برهان ریاضی برخوردار باشد (لئوناردو داوینچی)