الگوریتمستان

برنامه‌نویسی، طراحی الگوریتم و حل مسئله‌های الگوریتمی

 
در صورت ناخوانا بودن نوشته‌ها، از مرورگر دیگری استفاده کنید.
توابع دوست کلاس در ++C - الگوریتمستان
الگوریتمستان
  »  

توابع دوست کلاس در ++C

        آشنایی با توابع دوست کلاس در زبان برنامه‌نویسی ++C و کاربرد آنها در سربارگذاری عملگرها
آنچه می‌خوانید ویراست جدید نوشته‌ای است که اولین بار با عنوان «توابع دوست کلاس» بهمن ماه ۱۳۸۵ از طریق وبگاه برنامه‌نویسی و طراحی الگوریتم (عنوان و طرح پیشین وبگاه الگوریتمستان) منتشر شده بود.
آنچه در این نوشته می‌خوانید:

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

به زبان ساده، توابع دوست یک کلاس توابعی هستند که عضو کلاس نیستند، اما به تمامی داده‌ها و توابع خصوصی و محافظت شده‌ی آن دسترسی دارند.

یک مثال ساده

  [بازگشت به فهرست]

  

class myclass {
    friend void print_a(myclass);
  private:
    unsigned a;
  public:
    myclass(int r) {
      a = r > 0 ? r : - r;
    }
    void print() {
10       cout << a;
11     }
12 };
13   
14 void print_a(myclass ob) {
15   cout << ob.a;
16 }
17 
18 void main() {
19   myclass ob(9);
20   ob.print();
21   cout << "\t";
22   print_a(ob);
23 }

  

خروجی به این صورت است:

  

9    9

  

تابع دوست print_a علیرغم اینکه عضو کلاس myclass نیست، اما به عضو خصوصی a از کلاس دسترسی دارد.

این قطعه برنامه روش استفاده از توابع دوست را نشان می‌دهد. توابع دوست با کلمه‌ی کلیدی friend در ابتدای تعریفشان مشخص می‌شوند. توجه داشته باشید که چون این توابع عضو کلاس نیستند نباید عملگر تعیین حوزه (::) زمان تعریف بلوک بدنه‌ی آنها استفاده شود. یعنی این عبارت نادرست است:

  

void myclass::print_a(myclass ob)

  

چرا که ممکن است یک تابع، تابع دوست برای چندین کلاس مختلف باشد. درضمن بلوک بدنه این توابع باید بیرون از تعاریف هر کلاسی نوشته شوند.

اما چرا به توابع دوست نیاز داریم؟ چه کاربردهایی دارند که علیرغم نقض آشکار قوانین شیءگرایی از آنها استفاده می‌شود؟

  

سربارگذاری عملگرها با توابع دوست

  [بازگشت به فهرست]

قبلا در مورد سربازگذاری عملگرها در زبان ++C مطلبی ارائه شده است. در این مطلب تاکید شده بود که برای عملگرهای دودویی (مثل جمع و ضرب و ...) شیء سمت چپ، تابع عملگر مربوطه را فراخوانی می‌کند و شی سمت راست به عنوان آرگومان به تابع ارسال می‌شود. به عنوان مثال اگر عملگر + برای کلاسی سربارگذاری شده باشد، دو عبارت زیر معادل هم هستند:

  

ob1 + ob2    ≡    ob1.operator+(ob2)

  

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

  

comp operator + (double f)

  

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

اینجاست که تابع دوست به کمک ما می‌آید. به تعریف زیر دقت کنید:

  

friend comp operator + (double f , comp c)

  

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

  

c2 = 3.5 + c1;

  

کد کامل این کلاس به این صورت خواهد بود:

  

class comp {
    friend comp operator + (double, comp);
  private:
    double real, imag;
  public:
    comp(double r, double i) {
      real = r;
      imag = i;
    }
10     comp operator + (comp r) {
11       comp temp(real + r.real, imag + r.imag);
12       return temp;
13     }
14     comp operator + (double r)< {/P>
15       comp temp(real + r, imag);
16       return temp;
17     }
18 };
19   
20 comp operator + (double l, comp r) {
21   comp temp(l + r.real, r.imag);
22   return temp;
23 }

  

تذکر: این تعریف برای کلاس اعداد مختلط به هیچ وجه کامل نیست و تنها قسمت کوچکی از آن را شامل می‌شود. البته کتابخانه‌های زبان ++C هم برای کار با اعداد مختلط توابع و کلاس‌هایی دارند که همه‌ی نیازها را برآورده می‌کنند.

نکته‌ی مهم: برای سربارگذاری عملگرهای جریان (یعنی >> و <<) چاره‌ای ندارید جز این که از توابع دوست استفاده کنید (چرا؟).

به اشتراک‌گذاری نوشته
اشتراک‌گذاری در LinkedIn     Cloob     اشتراک‌گذاری در Twitter     اشتراک‌گذاری در Facebook     ارسال با Telegram     Google Plus
برچسب‌ها
امتیاز نوشته
  • 1
  • 2
  • 3
  • 4
  • 5

نام: *  

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

وبگاه:

متن پیام: *

01 02 03 04 05 06 07 08 09 10 11 12 13 14

 


• مرتضی
سه‌شنبه، ۱۰ آذر ماه ۱۳۸۸، ساعت ۱۸:۴۷

باسلام.

ضمن تبریک به داشتن چنین وب سایت عالی و پرباری.....

یه سوال دارم:

من دارم یه برنامه مینویسم که شبیه برنامه های نوشته شده با ویژوال هستش، تو این برنامه کلاس های خیلی زیادی نوشتم، حالا میخوام یه کلاس convert بنویسم که همه کلاس ها بتونن بدون ساختن یک شئ ازاون،بتونن ازش استفاده کنن.یعنی هر کلاس جدیدی هم که تعریف میکنم،بتونه بدون ساختن شئی از اون ازش استفاده کنه.چون میخوام این کلاس بین همه کلاس ها مشترک باشه.چطور؟؟

راستی من اصلا برنامه نویسی استاتیک بلد نیستم.

ممنوووون.

سه‌شنبه، ۱۰ آذر ماه ۱۳۸۸، ساعت ۲۰:۰۶
مسعود اقدسی‌فام

سلام

ممنون از لطفت.

شما می خوای با ++C برنامه بنویسی؟ یعنی می خوای همه کلاسهایی که داری بتونن از محتویات این کلاس به صورت مستقیم استفاده کنن؟


• نجمه
شنبه، ۲۲ خرداد ماه ۱۳۸۹، ساعت ۱۲:۰۷

باسلام

ميشه در سايتتون در مورد توابع عضو استاتيك مطالبي را بيان كنيد.اگر مطالب جنبه كنكوري داشته باشند بهتر است.ممنون


• alireza
دوشنبه، ۲۹ شهریور ماه ۱۳۸۹، ساعت ۱۲:۰۹

سلام دوست عزیز

امیدوارم که در کمال صحت و سلامتی باشی

آق من تو یه شرکت کار میکنم که قسمت عمدهکارش برنامه سازی هست

اما من تو فیلد سخت افزار و راه اندازی سیستم های تولیدی کار میکنم

خیلی  دوست دارم تو فیلد سی پلاس پلاس  وارد بشم

اما  نشده

می خوام کمکم کنی و جزوه خوب و روان و قدم به قذم اگه داری بهم بدی

ذوستان همکار کتاب مرجع لاتین  زیاد دادن اما اینها سنگین هست و به درد آدم مبتدی نمی خوره

ممنون


• زهرا
سه‌شنبه، ۹ خرداد ماه ۱۳۹۱، ساعت ۱۲:۳۴

با سلام من دانشجوی کارشناسی کامپیوتر هستم اگر می توانید در حل  ونوشتن این برنامه به من کمک کنید

اشیا زیر را در نظر بگیرید ستسته مراتبی از کلاسها را برای انها به همراه مجموعه مناسبی از توابع با وراثتی برای محاسبه حجم سطح و محیط (به شکل مناسب) توسعه دهید:جعبه - دایره- مربع- مثلث- چند ضلعی-خط- نقطه- شئ-چهار ضلعی - کره -مربع و چهار ضلعی - متواضی الاظلاع- شش ضلعی - پنج ضلعی - چهار ضلعی -

با تشکر


• زهرا
سه‌شنبه، ۹ خرداد ماه ۱۳۹۱، ساعت ۱۲:۴۰

البته فقط به زبان c++

خط اول سوال :کلمه درست( سلسله مراتب ) است


مسعود
پنجشنبه، ۱۱ خرداد ماه ۱۳۹۱، ساعت ۱۵:۰۷

زهرا خانم چه کمکی از دست من بر می‌یاد؟


یکشنبه، ۱ مرداد ماه ۱۳۹۱، ساعت ۱۱:۵۳

070707070707

جرا من هرچی کتاب میخونم ++c رو یاد نمیگیرم/

070707070707

آخه چرا


• لطفی
پنجشنبه، ۱۹ مرداد ماه ۱۳۹۱، ساعت ۱۸:۲۳

سلام،اگه لطف جواب س<ال منو بدید ممنون میشم.

ازطریق برنامه سی++ وکلاس دوست(friend)

برنامه ای بنویسید که تاریخ تولد شخصی را با تاریخ امروز مقایسه کند اگر امروز تولدش بود پیام تبریک چاپ کند.

ممنونم.


• موسی
پنجشنبه، ۱۹ مرداد ماه ۱۳۹۱، ساعت ۱۸:۳۴

جواب سوالی که فرستادیم رو از کجا باید  پیدا کنیم.

پنجشنبه، ۱۹ مرداد ماه ۱۳۹۱، ساعت ۲۱:۳۲
مسعود اقدسی‌فام

سوالی پرسیده نشده که جواب داده بشه. به نظر درخواست برنامه می‌یاد که اگه قسمت بالای بخش ارسال پیام رو مطالعه کرده باشید، چنین درخواستی جواب نداره.


• mohmmad
یکشنبه، ۱ بهمن ماه ۱۳۹۱، ساعت ۲۱:۳۴

0202020202020202

کمک کمک کمک

چطوری میتونم درج در جریان را با استفاده از تابع عضو سربارگذاری کنم.


• سیاوش
جمعه، ۲۴ آبان ماه ۱۳۹۲، ساعت ۱۹:۵۸

با سلام و خسته نباشید

کد سورسی در c++ می خواستم که تعداد روز بین دو تاریخ شمسی رو حساب کنه و سال کبیسه و تعداد روزهای بعضی ماه ها (30و31روزه بودن) رو مشخص کنه .

اگه میشه پاسخ بدید چون استادمون درس نمیده و میاد سر کلاس و میگه فلان برنامه رو بنویسید و ما هم خوب یاد نمی گیریم .

خدا اجرتون بده

06


• F
چهارشنبه، ۲۵ اسفند ماه ۱۳۹۵، ساعت ۱۱:۲۰

سلام ببخشید من دنبال تمام توابع مربوط ب رشته هاباتوضیح ومثال میگردم البته به جز SizeوLength...ممنون

جمعه، ۲۷ اسفند ماه ۱۳۹۵، ساعت ۱۴:۵۶
مسعود اقدسی‌فام

سلام

به زودی در این مورد هم نوشته‌ای اضافه می‌شه.


• هانی شمس
شنبه، ۸ اردیبهشت ماه ۱۳۹۷، ساعت ۱۰:۳۸

مرسی بابت مطلب خوبی که گذاشتید یه سوالی داشتم دلیل اینکه دو نسخه از عملگر درج در جریان » داخل کلاس ostream وجود داره چی هستش؟

اگر دقت کنید یکیش به صورت تابع عضو کلاس ostream هستش اون یکی غیر عضو هستش در صورتی که جفتش رو میشد به صورت تابع عضو پیاده سازی کرد

member:

http://www.cplusplus.com/reference/ostream/ostream/operator%3C%3C/

non-member:

http://www.cplusplus.com/reference/ostream/ostream/operator-free/

یعنی در حقیقت سوالم این هست بر چه اساس سازنده های کتابخانه استاندارد تصمیم گرفتند که برای یک سری از انواع مثل کاراکتر عملگر >> را به صورت غیر عضو پیاده سازی کنند و برای سایر انواع عملگر >> به صورت عضو کلاس تعریف شده

جمعه، ۱۴ اردیبهشت ماه ۱۳۹۷، ساعت ۱۸:۴۵
مسعود اقدسی‌فام

سلام

خیلی ممنون.

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


• محمد جواد
جمعه، ۱۴ اردیبهشت ماه ۱۳۹۷، ساعت ۱۴:۰۹

سلام علیکم

یک سوال در مورد این نکته ی پایانی

(نکته‌ی مهم: برای سربارگذاری عملگرهای جریان (یعنی >> و <<) چاره‌ای ندارید جز این که از توابع دوست استفاده کنید (چرا؟).)

چرا باید یک چنین چیزی باشد؟؟؟؟؟؟

با تشکر

جمعه، ۱۴ اردیبهشت ماه ۱۳۹۷، ساعت ۱۸:۳۶
مسعود اقدسی‌فام

سلام

چون در این حالت شی سمت چپ از نوع متعیرهای جریان (مثل cin و cout) هست و شی‌ای از نوع کلاس خودمون نیست.


الگوریتمستان در تلگرام

   

   

پیوند کوتاه: عمر نوشته:  ۳۴۸۳ روز
تعداد بازدید:  ۲۸۰۵۴ بازدید
تعداد امتیاز:  ۲۴ امتیاز
میانگین امتیاز:  ۳.۵۰  از  ۵.۰۰
»  نکته‌ای در مورد کلاس‌ها و مجموعه‌ها در ++C
        بررسی روش تعریف کلاس برای قابلیت استفاده از ظرف‌های مجموعه (set و unordered_set) در زبان برنامه‌نویسی ++C
»  sync_with_stdio در زبان ++C
        نکته‌ای در مورد کارایی عملیات ورودی و خروجی در زبان برنامه‌نویسی ++C و عملکرد تابع sync_with_stdio
»  نکته‌ای در محاسبه‌ی زمان اجرای کد
        در مورد تفاوت توابع clock و time در زبان برنامه‌نویسی ++C برای محاسبه‌ی زمان اجرای برنامه
»  هدر فایل bits/stdc++.h
        معرفی هدرفایل bits/stdc++.h برای کاهش زمان آماده شدن کد مسابقات برنامه‌نویسی
»  نکته‌ای از مسأله‌ی Graphical Editor
        استفاده از stringstream در حل سوالات مسابفات برنامه‌نویسی با زبان برنامه‌نویسی ++C
»  تابع popen
        روش اجرای برنامه‌ای دیگر داخل کد ++C و استفاده از خروجی آن
»  ظرف‌ها در ++C
        معرفی انواع ظرف‌ها (نگهدارنده‌ها - containers) در زبان برنامه‌نویسی ++C
»  نکته‌ای در استفاده از map
        نکته‌ای در مورد استفاده از ساختمان داده‌ی map با مثالی به زبان برنامه‌نویسی ++C
»  فایل سرآیند algorithm
        معرفی فایل سرآیند algorithm از کتابخانه قالب استاندارد زبان برنامه‌نویسی ++C به همراه نمونه کد
»  کلاس‌های حافظه در ++C
        آشنایی با کلاس‌های حافظه و کاربرد آنها در زبان ++C
»  حلقه‌های تکرار در ++C
        آشنایی با حلقه‌های تکرار در زبان برنامه‌نویسی ++C و دستورات کنترلی مورد استفاده در آن
»  نکات مهم در برنامه‌نویسی به زبان ++C
        پنج نکته‌ی آموزنده در مورد برنامه‌نویسی به زبان برنامه‌نویسی ++C
»  سربارگذاری عملگرها در ++C
        آشنایی با مفهوم سربارگذاری عملگرها در زبان ++C
»  متغیرهای مرجع در ++C
        معرفی متغیرهای مرجع در زبان برنامه‌نویسی ++C و آشنایی با مهمترین کاربردهای آنها