سربارگذاری عملگرها در ++C - الگوریتمستان
الگوریتمستان
3113.945.00
  »  

       

آشنایی با مفهوم سربارگذاری عملگرها در زبان ++C

http://www.aachp.ir آنچه می‌خوانید ویراست جدید نوشته‌ای است که اولین بار با عنوان «سربارگذاری عملگرها» آذر ماه 1385 از طریق وبگاه برنامه‌نویسی و طراحی الگوریتم (عنوان و طرح پیشین وبگاه الگوریتمستان) منتشر شده بود.


همانطور که می‌دانید، شیوه‌ی معرفی اشیاء کلاس‌های تعریف شده در ++C همانند متغیرهای عادی هستند. به عنوان مثال اگر کلاسی به نام myclass تعریف کرده باشیم، عبارت زیر یک شیء از این کلاس به نام a تعریف می‌کند:

  

myclass a;

  

    اما اشیاء کلاس یک تفاوت اساسی با متغیرهای معمولی (مانند int ،float ،char و ...) دارند و آن عدم پشتیبانی از عملگرها است. در واقع عملگر انتساب (=) تنها عملگر قابل استفاده برای اشیاء کلاس است. اشیاء کلاس به صورت پیش‌فرض از عملگرهای دیگر (همانند + ، - ، / ، >> ، & و * و ...) پشتیبانی نمی‌کنند. اگر b ،a‌ و c سه شیء از کلاس myclass باشند، عبارت زیر کامپایل نمی‌شود:

  

c = a + b;

  

    چرا که عمل جمع برای این اشیاء مفهومی ندارد. مگر اینکه خودمان زحمت مفهوم دادن به این عملگر را با استفاده از سربارگذاری عملگرها بکشیم. در واقع سربارگذاری به ما این امکان را می‌دهد که عملکرد هر عملگر را برای کلاس مشخص کنیم.

    توجه داشته باشید که اگر کلاس ما حاوی دستوراتی برای تخصیص حافظه باشد، حتی عملگر انتساب پیش‌فرض هم قابل استفاده نیست. به قطعه کد زیر توجه کنید:

  

class myclass {
    char *str;
  public:
    myclass(int n) {
      str = new char[n];
    }
    ~myclass() {
      delete[] str;
    }
10     .
11     .
12     .
13 };

  

    اگر a و b دو شیء از این کلاس باشند، عبارت زیر یک خطای منطقی بسیار بزرگ را به دنبال دارد:

  

a = b;

  

    در وهله‌ی اول به نظر می‌آید که این عبارت مشکلی نداشته باشد. اما اینطور نیست. حین عمل انتساب، محتویات اشاره‌گر str مربوط به شیء b به همتای خودش در شیء a کپی می‌شود. این عمل باعث بروز دو مشکل می‌شود: اولا محتویات اشاره‌گر str شیء a (و در واقع آدرس حافظه‌ی پویای اختصاص پیدا کرده توسط شیء a) از دست می‌رود که متعاقب آن نمی‌توان حافظه‌ی اختصاصی را آزاد کرد. ثانیا a و b از حافظه‌ی مشترک استفاده می‌کنند که به احتمال بسیار زیاد باعث ایجاد اختلال در برنامه خواهد شد.

    همین مثال ساده نشان می‌دهد استفاده از سربارگذاری عملگرها از بروز چه مشکلاتی جلوگیری می‌کند. شما با تعریف مجدد عملگر انتساب برای این کلاس می‌توانید از بروز خطا جلوگیری کنید.

    فرض کنید کلاسی داریم به نام complex که برای کار با اعداد مختلط ایجاد شده است. این کلاس می‌تواند به صورت زیر تعریف شده باشد:

  

class complex {
  private:
    double r, i ;
  public:
    complex(int a = 0, int b = 0) {
      r = a;
      i = b;
    }
};

  

    این کلاس دو متغیر خصوصی دارد که برای ذخیره کردن قسمت حقیقی (r) و موهومی (i) عدد مختلط به کار می‌روند.

    حال می‌خواهیم عملگر جمع را برای این کلاس تعریف کنیم.

  

complex operator + (const complex &b) {
  complex temp;
  temp.r = this->r + b.r;
  temp.i = this->i + b.i;
  return temp;
}

  

    این تعریف ساده، عملگر + را برای جمع زدن دو عدد مختلط تعریف می‌کند. البته با این تعریف، کار سربارگذاری کامل عملگر + برای اعداد مختلط تمام نمی‌شود. ممکن است بخواهیم یک عدد حقیقی (یعنی متغیرهای معمولی ++C مانند int ،float و . . .) را با عدد مختلط جمع کنیم. تابع فوق تنها می‌تواند دو شیء از کلاس complex را با هم جمع کند و نه بیشتر.

    این تابع یک ورودی دارد و یک خروجی. تکلیف خروجی تابع کاملا مشخص است. حاصل جمع دو عدد مختلط یک عدد مختلط است. پس تابع جمع، یک شیء از نوع complex را بر می‌گرداند. اما بر خلاف تصور اولیه‌ی ما، این تابع فقط یک ورودی دارد. در حالی که ما دو شیء را با هم جمع می‌کنیم. در واقع تابع جمع توسط شیء سمت چپ عملگر فراخوانی و شیء سمت راست به عنوان پارامتر به تابع ارسال می‌شود. به عنوان مثال فرض کنید که دو شیء c1 و c2 از کلاس complex در اختیار داریم. وقتی کامپایلر به عبارتی مانند c1 + c2 بر می‌خورد، آن را به صورت زیر تفسیر می‌کند:

  

c1.operator + (c2)

  

    به همین خاطر برای دسترسی به اعضای شیء سمت چپ (در اینجا c1) باید از اشاره‌گر ضمنی this استفاده کنیم. تابع جمع بالا به غیر از مواردی که بحث کردم مورد دیگری ندارد.

    تابع فوق فقط برای جمع دو شیء از کلاس complex کاربرد دارد. حالت دیگری که ممکن است به وجود بیاد، جمع کردن یک متغیر معمولی ++C با اشیاء این کلاس است. همانطور که می‌دانید عمل جمع بین اعداد مختلط و حقیقی تعریف شده است. هر عدد حقیقی یک عدد مختلط با قسمت موهومی صفر است. این حالت خود به دو صورت اتفاق می‌افتد: عدد سمت چپ مختلط و عدد سمت راست حقیقی باشد، یا عدد سمت چپ حقیقی و عدد سمت راست مختلط باشد. حالت دوم نیاز به آشنایی با توابع دوست کلاس دارد. اما برای حالت اول می‌توانیم از تابع زیر استفاده کنیم:

  

complex operator + (double x) {
  complex temp;
  temp.r = this->r + x ;
  temp.i = this->i ;
  return temp ;
}

  

    تابع بالا دقیقا مانند تابع اولی تعریف شده است. با این تفاوت که پارامتر ورودی آن از شیء complex به متغیر از نوع double تغییر پیدا کرده است. به عنوان مثال عبارت c1 + 2.5 به این صورت تفسیر می‌شود:

  

c1.operator + (2.5)

  

    به همین راحتی عملگر + برای اعداد مختلط تعریف شد. البته باید به نکات مهم زیر توجه کنید:

    1- هنوز حالتی را که عملوند سمت چپ یک متغیر غیر مختلط باشد بررسی نکرده‌ایم.

    2- در تابع دوم لزومی ندارد که عدد ورودی حتما اعشاری باشد. ++C از تغییر موقت متغیر برای امکان استفاده از اعداد صحیح پشتیبانی می‌کند.

    3- دو تابع مذکور بدون هیچ مشکلی می‌توانند هم‌زمان در یک کلاس تعریف شوند. ++C از سربارگذاری توابع (تعریف چند تابع با یک نام، اما با پارامترهای متفاوت) پشتیبانی می‌کند.

    4 - تعاریف بالا تعریف عملگر جمع پیش فرض ++C را مخدوش نمی‌کند. یعنی برای جمع دو عدد صحیح یا اعشاری هیچ مشکلی ایجاد نمی‌کند.

    5- علت استفاده از const و متغیر مرجع در پارامتر تابع اول مربوط به کاربرد متغیرهای مرجع است که قبلا در این مورد مطلبی نوشته‌ام.

    6- در تعاریف بالا لزومی به استفاده از اشاره‌گر ضمنی this وجود ندارد. اما برای خوانایی بیشتر کد معمولا از این روش استفاده می‌شود. دو عبارت this->r و r با هم معادل هستند.

    7- توابع سربارگذاری عملگرها حتما باید در قسمت public کلاس تعریف شوند.

  

+

-

*

/

%

^

&

|

~

!

=

<

>

+=

-=

*=

/=

%=

^=

&=

|=

<<

>>

>>=

<<=

==

!=

<=

>=

&&

||

++

--

->*

,

->

[]

()

new

delete

new []

delete []

عملگرهایی را که می‌توان مجددا تعریف کرد


پیوندها برای مطالعه‌ی بیشتر
نوشته‌های مرتبط
        معرفی انواع ظرف‌ها (نگهدارنده‌ها - containers) در زبان برنامه‌نویسی ++C
        آشنایی با توابع دوست کلاس در زبان برنامه‌نویسی ++C و کاربرد آنها در سربارگذاری عملگرها
        معرفی فایل سرآیند algorithm از کتابخانه قالب استاندارد زبان برنامه‌نویسی ++C به همراه نمونه کد
        معرفی متغیرهای مرجع در زبان برنامه‌نویسی ++C و آشنایی با مهمترین کاربردهای آنها
        آشنایی با کلاس‌های حافظه و کاربرد آنها در زبان ++C
        آموزش استفاده از آرایه‌ی پویای دو بعدی در زبان ++C
        آشنایی با حلقه‌های تکرار در زبان برنامه‌نویسی ++C و دستورات کنترلی مورد استفاده در آن
        آشنایی با مفهوم و عملکرد اشاره‌گرها در زبان برنامه‌نویسی ++C و ارائه مثالهایی از کاربرد آن
        پنج نکته‌ی آموزنده در مورد برنامه‌نویسی به زبان برنامه‌نویسی ++C
        آشنایی با قالب‌ها به عنوان یکی از امکانات متمایز ++C از C
پیوند کوتاه صفحه دسته‌بندی
امتیاز نوشته
  • 1
  • 2
  • 3
  • 4
  • 5
ارسال پیام

نام: *  

پست الکترونیک:

وبگاه:

متن پیام: *

 


» mahdiye

سه‌شنبه، ۲۴ فروردین ماه ۱۳۸۹، ساعت ۱۹:۵۳
02
salam mamnoon az matalebi ke gozashtin
mishe class be c++  programing :
تاریخ
درس
student
اعداد مختلط
دایره
مستطیل
کتاب
اعداد کسری
خیلی فوریه !!!!!!!!!!!!!!!!

» سارا

سه‌شنبه، ۱۴ اردیبهشت ماه ۱۳۸۹، ساعت ۲۱:۵۴
سلام در صورت امکان لطفا سربارگذاری تمامی عملگرهارو برای اعداد گویا بنویسید

» محمد

پنجشنبه، ۲۰ خرداد ماه ۱۳۸۹، ساعت ۱۰:۲۳
خواهشا کمکم کنید تا در ++c کلاسی تعریف کنم و در اون عملگرهای +و-و* را برای عملیات روی ماتریس ها مجددا تعریف کنم.مرسی.

» مریم

جمعه، ۹ مهر ماه ۱۳۸۹، ساعت ۰۱:۲۶
ممنون
خیلی جامع و خوب نوشتید..

» ali

پنجشنبه، ۲۵ آذر ماه ۱۳۸۹، ساعت ۰۱:۰۶
agha salam.n tamrin forie jane man ye karish konid
کلاسي به نام integerset ايجاد کنيد. هر شيء از اين کلاس مي تواند اعدادي صحيح در بازه 0 تا 100 را بپذيرد. مجموعه به صورت آرايه اي از صفرها و يک ها نشان داده مي شود. اگر عدد صحيح i در مجموعه باشد، a[i] برابر با يک است. عنصر a[j] در صورتي صفر است که j در مجموعه نباشد.
{1,3,5,6}=[0,1,0,1,0,1,1]
سازنده مجموعه را طوري مقدار اوليه مي دهد که تمام عناصر آرايه صفر باشد.
عملگر + را به گونه اي تعريف کنيد که اجتماع دو مجموعه را حساب کند.
عملگر – را به گونه اي تعريف کنيد که اشتراک دو مجموعه را حساب کند.
عملگر == را به گونه اي تعريف کنيد که مشخص کند آيا دو مجموعه با هم برابرند؟
عملگر – را به گونه اي تعريف کنيد که مکمل يک مجموعه را حساب کند.
توابع عملگر را يک بار به عنوان اعضاي کلاس و بار ديگر، به عنوان توابع دوست تعريف  نماييد.
در دو برنامه مجزا کلاس خود را تست نماييد.

» parisa

یکشنبه، ۵ دی ماه ۱۳۸۹، ساعت ۲۰:۲۲
salam bebakhshid mishe barnameye in soalo vasam mail konid kheyli hayatiye
کلاسي به نام integerset ايجاد کنيد. هر شيء از اين کلاس مي تواند اعدادي صحيح در بازه 0 تا 100 را بپذيرد. مجموعه به صورت آرايه اي از صفرها و يک ها نشان داده مي شود. اگر عدد صحيح i در مجموعه باشد، a[i] برابر با يک است. عنصر a[j] در صورتي صفر است که j در مجموعه نباشد.
{1,3,5,6}=[0,1,0,1,0,1,1]
سازنده مجموعه را طوري مقدار اوليه مي دهد که تمام عناصر آرايه صفر باشد.
عملگر + را به گونه اي تعريف کنيد که اجتماع دو مجموعه را حساب کند.
عملگر – را به گونه اي تعريف کنيد که اشتراک دو مجموعه را حساب کند.
عملگر == را به گونه اي تعريف کنيد که مشخص کند آيا دو مجموعه با هم برابرند؟
عملگر – را به گونه اي تعريف کنيد که مکمل يک مجموعه را حساب کند.
توابع عملگر را يک بار به عنوان اعضاي کلاس و بار ديگر، به عنوان توابع دوست تعريف  نماييد.
در دو برنامه مجزا کلاس خود را تست نماييد.

» نسترن

یکشنبه، ۷ اسفند ماه ۱۳۹۰، ساعت ۲۰:۰۲
مرسی از توضیحات خوبتون میشه سربارگذاری رو واسه عملگر های > و < و == و != و >= و =< توضیح بدین لطفا؟؟؟ خییییلی فوریه!!

» soheil

سه‌شنبه، ۲۱ آذر ماه ۱۳۹۱، ساعت ۰۲:۳۶
آقا خداوکیلی عجب سایتی دارید.یه عمره دنبال یه سایت مثل شما میگردم.خداییش خیلی عالیه
با تشکر
Soheil
www.1ke.ir

» sanaz

شنبه، ۱۱ خرداد ماه ۱۳۹۲، ساعت ۱۰:۳۹
kheili kheili ali boooooooood:)

» مجید

شنبه، ۱۸ آبان ماه ۱۳۹۲، ساعت ۱۲:۴۶
سلام و خسته نباشید.
من برای تعریف یک آرایه از اعداد مختلط توی c++ به کمک احتیاج دارم.لطفا راهنماییم کنین . ممنون .

» زهرا

جمعه، ۲۶ اردیبهشت ماه ۱۳۹۳، ساعت ۲۲:۰۵
سلام ببخشید میشه جواب این تمرینو برام ایمیل کنید خیلی فوریه و حیاطی برای فردا لازمش دارم یه دنیا ممنون!
-----------------------------------------------------
کلاسي به نام integerset ايجاد کنيد. هر شيء از اين کلاس مي تواند اعدادي صحيح در بازه 0 تا 100 را بپذيرد. مجموعه به صورت آرايه اي از صفرها و يک ها نشان داده مي شود. اگر عدد صحيح i در مجموعه باشد، a[i] برابر با يک است. عنصر a[j] در صورتي صفر است که j در مجموعه نباشد.
{1,3,5,6}=[0,1,0,1,0,1,1]
سازنده مجموعه را طوري مقدار اوليه مي دهد که تمام عناصر آرايه صفر باشد.
عملگر + را به گونه اي تعريف کنيد که اجتماع دو مجموعه را حساب کند.
عملگر – را به گونه اي تعريف کنيد که اشتراک دو مجموعه را حساب کند.
عملگر == را به گونه اي تعريف کنيد که مشخص کند آيا دو مجموعه با هم برابرند؟
عملگر – را به گونه اي تعريف کنيد که مکمل يک مجموعه را حساب کند.
توابع عملگر را يک بار به عنوان اعضاي کلاس و بار ديگر، به عنوان توابع دوست تعريف  نماييد.
در دو برنامه مجزا کلاس خود را تست نماييد.

» AK47dev

یکشنبه، ۳۰ خرداد ماه ۱۳۹۵، ساعت ۲۳:۲۷
من نمیدونم چرا انقد سایتتون خوبه 10
ارث بری رو هم فقط اضافه کنید
کارتون بیسته
ممنون
یا علی 060606

» محمد

یکشنبه، ۲۱ آذر ماه ۱۳۹۵، ساعت ۱۴:۴۷
ممنون از اطلاعات عالیتون خیلی بدردم خورد06