آژانس هواپیماییdaftare shoma
nexpay

كلاس در سي ++

شروع موضوع توسط saalek ‏22 ژانویه 2006 در انجمن خانواده C++ , C

  1. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
  2. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    من از ابتدا كه تاپيك اصلي را باز كردم ، هدفم بحث كلاس بود، به همين خاطر عنوان تاپيك را سي ++ گذاشتم نه سي.

    در فاز يك ، هدف اين تاپيك اينه كه بتوانيم كلاس هاي ساده بسازيم و اگر سورسي حاوي كلاس بود ، درك كنيم كه چطور برنامه كار مي كند.

    اما به نظر من كلاس يك تعريف ساده است و من بيشتر توجه خود را روي ريزه كاريهاي تاپيكهاي ديگر مي گذارم. مثل ارتباط با فايل ، مديريت حافظه، و جنبه هاي بيتي سي.
    .
    در مورد كلاس با كتاب sams شروع مي كنيم چون ساده گفته ولي ممكنه از يك كتاب ديگه از اول شروع كنيم بعدا. يعني عقب گرد در تاپيك ممكنه اتفاق بيافته. در تاپيك اصلي هم اين قضيه اتفاق افتاد كه بعدا بايد مرتب بشه و رديف بشه پستها.
    .
     
  3. mohammad_110

    mohammad_110 کاربر فعال برنامه نویسی کاربر فعال

    تاریخ عضویت:
    ‏22 ژانویه 2006
    نوشته ها:
    60
    تشکر شده:
    0
    اول یه تاریخچه ای از روشهای برنامه نویسی بگیم بد نیست : (از کتاب آموزش Turbo C++ ترجمه : کیوان فلاح مشفقی )

    قدیمیترین الگوهای برنامه نویسی را به بهترین وجه ممکن می توان توسط صفت هرج و مرج توصیف کرد .

    در این مدل تمام فکر و ذکر طراحان تنها به حل کردن مشکل مورد نظر معطوف است و توجه اندکی به چگونگی رسیدن به این راه حل دارند (و یا اینکه کلا به این موضوع توجهی ندارند). زبانهایی که در طبقه هرج و مرج می گنجند عبارتند از انواع اولیه Basic ( که حتی فاقد ساختار برنامه فرعی بودند).

    تحت این شیوه استفاده کننده به هیچوجه با افکاری نظیر نحوه سازماندهی برنامه یا توسعه آتی آن درگیر نمی شود و تمام توجه وی بر روی مشکل مورد نظر متمرکز می گردد. پس از آنکه برنامه نوشته شده تحت این الگو ، به هر ترتیب ، شروع به کار نمود عملکرد آن تنها به برنامه های بسیار ساده محدود می گردد ( یعنی برنامه های کمتر از صد خط ) .

    در مورد برنامه هایی که ابعاد آنها از این حد بیشتر می شد تعداد مسیرهای این نوع برنامه ها ( که بدون شک بسیار زیاد خواهند بود ) عمل اشکال زداییو بررسی برنامه را به یک کابوس شبانه تبدیل خواهند کرد ( این همان مشکل کلاسیک شیوه کد اسپاگتی Spaghetti code است ).
     
  4. mohammad_110

    mohammad_110 کاربر فعال برنامه نویسی کاربر فعال

    تاریخ عضویت:
    ‏22 ژانویه 2006
    نوشته ها:
    60
    تشکر شده:
    0
    اولین پیشرفت نسبت به شیوه هرج و مرج الگوی برنامه نویسی پروسه ای Procedural بود .

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

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

    در واقع در این حالت بین برنامه اصلی و داده ها یک دیوار بلند وجود دارد . در این روش کلیه توجه برنامه نویس به ایزوله کردن برنامه معطوف است و وی توجهی به داده ها ندارد.
     
  5. mohammad_110

    mohammad_110 کاربر فعال برنامه نویسی کاربر فعال

    تاریخ عضویت:
    ‏22 ژانویه 2006
    نوشته ها:
    60
    تشکر شده:
    0
    تغییر بعدی در این زمینه الگوی برنامه نویسی ساخت یافته Structured است که در آن تجرید برنامه به ماورا توابع نیز گسترش می یابد . ( توجه کنید که اینجا استراکت به دو معنی اومده یکیش رو که می دونید یکیش هم منظور ساختار برنامه است )

    در این حالت به جای آنکه بین توابع هرج و مرج برقرار باشد (چنانچه در روش پروسه ای چنین است ) ، برنامه نویس ساخت یافته قوانینی را ارائه می کند که برنامه نویس را قادر می سازد هر سازه( Struct ) ، نظیر : بلوکهای for ، while ، if را بعنوان یک زیر تابع یا تابع فرعی ( Subfunction) کوچک در نظر بگیرد.

    خود این توابع فرعی را می توان متعاقبا ایزوله کرد. به عنوان مثال در این حالت استفاده کنندگان می توانند یک حلقه for را به عنوان یک قسمت مستقل در نظر بگیرند ، زیرا آنها می دانند که کلیه مسیرهای ورودی و خروجی به حلقه مشخص هستند و هیچگونه مسیری به اواسط حلقه وجود ندارد ( یعنی نمی توان به یکباره به وسط حلقه دسترسی یافت و چند عمل را انجام داد و سپس از آن بیرون رفت ). به منظور پشتیبانی از یک الگوی ساخت یافته ( Structured ) ، یک زبان باید محتوی مجموعه ای کامل از سازه های کنترلی ( Control Structures ) باشد. یک نمونه مناسب از اینگونه زبانها پاسکال است.

    در الگوی برنامه نویسی ساخت یافته دیگر داده ها نادیده گرفته نشده اند . در این الگو قوانینی در مورد ارسال داده ها بین توابع وجود دارد . توابع ملزم هستند تنها به آن داده هایی دسترسی داشته باشند که آنها را به عنوان آرگومانهای ( arguments ) ورودی قبول نموده اند و برقراری ارتباط از طریق متغیر های عمومی ( global variable ) به هیچوجه توصیه نمی گردد.

    این محدویدیت ها در واقع عکس العملی بود نسبت به ضعف مدل پروسه ای ( Procedural ) . کار با یک تابع به عنوان یک جسم تجریدی ( یا به عبارتی ایزوله نسبت به دنیای خارج )، در صورتیکه تابع بتواند متغیرهای عمومی را دریافت کرده و آنها را تغییر دهد ، عمل بسیار دشواری خواهد بود. از آنجاییکه سر و کار داشتن و تحت قاعده در آوردن نتایج حاصله از این عمل دشوار است، مسیرهای ارتباطاتی مشخصی بوجود آمدند که توصیف آنها ساده تر است. با این وجود تبعیت از این قوانین اختیاری است و از اینرو بین همه استفاده کنندگان مختلف مشترک نیست.

    اکثر زبانهای برنامه نویسی ساخت یافته ( Structured ) برنامه نویسان خود را تشویق می کنند که انواع داده ای (Data Type ) جدیدی را تعریف نمایند که بتواند توصیفی دقیفتر از شی ( Object ) حقیقی ایجاد کند . در C انواع داده ای ساده را می توان توسط عبارات enum یا typedef تعریف کرد .

    انواع داده ای پیچیده ای بدون شک نیاز به تعریف یک سازه ( Structre ) بخصوص دارند. تعاریف سازه ای جهت در کنار یکدیگر قرار دادن داده های مشابه مورد استفاده قرار می گیرند. در این حالت داده ها در یک واحد منفرد که پس از مدل شدن تا حداکثر ممکن به ( Object ) واقع در دنیای واقعی شباهت دارد گردآوری می شوند.
     
  6. mohammad_110

    mohammad_110 کاربر فعال برنامه نویسی کاربر فعال

    تاریخ عضویت:
    ‏22 ژانویه 2006
    نوشته ها:
    60
    تشکر شده:
    0
    در برنامه نویسی مدولار ( Modular ) یا قطعه قطعه که در واقع نوع توسعه یافته ای از الگوی برنامه نویسی ساخت یافته محسوب می گردد توابع باز هم به فایلهای برنامه ای مجزای سازگار با یکدیگر بیشتری تقسیم می گردند .

    به هر یک از این تکه برنامه ها یک مدول ( Module ) یا به عبارتی ماژول گفته می شود . هر مدول دارای مجموعه ای از توابع و داده هاست که تنها خود وی به آنها دسترسی دارد و در ضمن یک مجموعه جداگانه از توابع و داده ها وجود دارند که در دسترس کلیه مدولها می باشند.

    کلیه توابع مشابه در داخل یک مدول جای می گیرند و ضرورتی ندارد که کلیه توابع تعریف شده در داخل یک مدول در خارج از آن نیز شناخته شده باشند. محدود کردن تعداد توابع عمومی تعریف شده سبب کاهش تعداد مسیرهای ارتباطی مورد نیاز بین مدولها شده و از اینرو سبب کاهش پیچیدگی کل سیستم می گردد .

    در این الگو همچنین عمل پنهان کردن داده ها ( data hiding ) یا کپسوله کردن ( encapsulating ) آنها امکان پذیر شده است. در این حالت داده هایی که توسط توابع جداگانه ای مورد استفاده قرار می گیرند از مدولهای دیگر پنهان می گردند . بنابراین برنامه نویس می تواند یک سازه داده ای ( Data Structure ) جدید تعریف کرده و توسط آن مجموعه ای از توابعی که باید با آنها به کار پرداخته شود شود را معرفی نماید . در این حالت دیگر مدولهایی که در خارج از مدول تعریف شده می باشند می توانند این سازه را به عنوان یک نوع داده ای ( data type ) جدید که تنها از توابعی که جهت دسترسی عمومی به آن در نظر گرفته شده اند استفاده می کند در نظر بگیرند.

    داده هایی که در خارج از این مدولها نیز شناخته شده هستند داده های عمومی ( public ) نامیده می شوند و در مقابل ، از داده های دیگر ( که مدولها ممکن است از آنها جهت کار با یک نوع داده ای جدید استفاده کنند و یا آن آن داده هایی که در خارج از یک مدول قابل مشاهده نیستند ) بعنوان داده های خصوصی ( private ) یاد می شود. در C از المانها ( elements ) یا عناصری که استاتیک یا اتوماتیک ( automatic ) می باشند بعنوان خصوصی و از مابقی عناصر به عنوان عمومی یاد می شود.

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

    در این حالت دیگر برنامه نویس می تواند یک الگوریتم ( algorithm ) را با نگرانی و تردید کمتری جهت کار با سازه های داده ای مورد استفاده قرار دهد . جزئیات مربوط به نوع سازه ( Structre type ) در داخل مدول تعریف شده پنهان می گردد. عمل اصلاح و تغییر دادن سازه های داده ای را نیز اغلب می توان با تغییر دادن مدول تعریف شده به انجام رساند ، بدون آنکه به مدولهای اصلی دیگر تغییری وارد گردد. در بهترین برنامه های به زبان C از این الگوی برنامه نویسی استفاده می شود.
     
  7. mohammad_110

    mohammad_110 کاربر فعال برنامه نویسی کاربر فعال

    تاریخ عضویت:
    ‏22 ژانویه 2006
    نوشته ها:
    60
    تشکر شده:
    0
    متاسفانه تبعیت از این الگو در C اختیاری است . در این حالت اگر در یک عنصر از یک سازه یک مقدار نامعتبر وجود داشته باشد برنامه نویس نمی تواند مطمئن باشد که آیا علت این امر آن است که توابع دسترسی این مقدار را در این مکان ذخیره کرده اند و یا اینکه یک مدول بی وجدان مستقیما به عناصر سازه مورد بحث دسترسی پیدا کرده است . زبانهایی که از الگوی کپسوله کردن داده ها پشتیبانی می کنند استفاده کننده را به استفاده از توابع دسترسی مقید می کنند.

    ساختار هر نوع داده ای جدیدا ایجاد شده نباید با انواع داده ای از پیش ساخته موجود در زبان برنامه نویسی مورد نظر شباهت داشته باشد . داده هایی که از الگوی ایزوله کردن داده ها پشتیبانی می کنند برنامه نویس را قادر می سازند تا عملگرهای ( operators ) ویژه مورد نیاز جهت انواع داده ای جدیدا تعریف شده خود را نیز تعریف کند. به عنوان مثال با تعریف یک نوع داده ای جدید با نام Complex برنامه نویس می تواند عملگرهای ریاضی ساده ( یعنی : + ، - ، * ، / ) را در مورد این نوع داده ای تعریف کند به عبارت دیگر برنامه نویس می تواند تعریف نماید که منظور وی از وارد کردن دستور زیر چیست :
    کد:
    Complex A, B, C;
    
    C = A + B;
    
    توجه داشته باشید که من اصطلاح تعریف مجدد ( redefine ) را به کار نبرده ام . عملگرهای ریاضی اولیه همچنان به قوت خود باقی می مانند.

    عمل ایزوله کردن ( abstraction ) داده ها برنامه نویس را قادر می سازد که در آینده ، در حین به کارگیری یک الگوریتم ، جزئیات را در نظر نگیرد . علاوه بر C++ ، زبان Ada متداولترین زبان برنامه نویسی است که می تواند از قابلیت ایزوله کردن داده ها پشتیبانی نماید.

    تعریف یک نوع داده ای جدید که شامل کلیه عملگرهای مورد نیاز نیز می باشد ، می تواند یک پروسه دست و پا گیر باشد ، بویژه برای شخصی که همواره باید کار را از ابتدا آغاز نماید .
    تعریف یک نوع داده ای (data type ) با توجه به انواع عملگرهای اولیه ، سبب نامفهوم شدن ارتباطات احتمالا موجود بین انواع عملگرهای تعریف شده توسط استفاده کننده ( user defined type ) خواهد شد.

    به عنوان مثال یک دانشجوی در حال تحصیل در یک کالج یک حالت بخصوص از یک دانشجو ( به مفهوم عمومی آن) است. این دو نوع ( یعنی دانشجوی کالج و یک دانشجو ، در حالت کلی ) در بسیاری از صفات با یکدیگر مشترکند. بنابراین اینکه ما یک نوع داده ای جدید با نام CollageStudent را با توجه به نوع داده ای اولیه Student ایجاد کرده و یه این ترتیب رابطه بین این دو را با یکدیگر مشخص کنیم عملی مفید خواهد بود. به این موضوع ارث بردن ( inheritance ) گفته می شود.

    با ایجاد چنین تعریفی باید بتوان بین این دو تعریف به عقب و جلو حرکت کرد. (یعنی بین این دو تعریف ارتباط برقرار نمود ). یک داده نوع CollageStudent باید بتواند به توابع تعریف شده جهت نوع Student دسترسی پیدا نماید . از اینرو تابعی که انتظار دارد یک اشاره گر ( pointer ) به یک داده از Student را دریافت نماید می تواند مستفیما یک اشاره گر به یک داده از CollageStudent را دریافت کند زیرا یک دانشجوی کالج نیز در واعق یک دانشجو است. به قابلیت تشخیص دادن انواع میراثی ( inherited types ) از یکدیگر پلی مورفیسم (Polymorphism ) گفته می شود.

    بنابراین ما مجددا به تعریف خود از زبانهای شئ- شناس ( object-oriented ) باز می گردیم. یک زبان نوع شئ-شناس می تواند از قابلیتهای کپسوله کردن ، ایزوله کردن ، ارث بردن ، و پلی مورفیسم پشتیبانی نماید.
    ++C از این خواص پشتیبانی می کند ، درست به همان ترتیب که پدر آن یعنی زبان C از خواص برنامه نویسی ساخت یافته پشتیبانی می کند.
     
  8. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    مطلب زير را از :
    http://www.hamkalam.com/forum/lofiversion/index.php/t521.html
    نقل مي كنم.
    جناب GoodBoy اين آموزش ها را زحمتش را كشيده. خيلي تميز هم كار كرده.

    مفاهيم برنامه نويسي شي گرا


    يك شي ( object ) چيست؟

    اشيا كليد فهم تكنولوژي شي گرايي است . شما مي توانيد با نگاه به محيط اطراف خود مثال هاي زيادي از اشياي دنياي واقعي را ببينيد
    دستگاه تلويزيون - دوچرخه - گربه - درخت - . . .
    اين اشياي واقعي داراي دو مشخصه هستند : ويژگي و رفتار
    براي مثال يك گربه داراي ويژگي هاي : نام - رنگ - سن - ارتفاع - . . .
    و داراي رفتار هايي مانند : صدا - پريدن - دويدن - راه رفتن - خوابيدن - . . .

    يك دوچرخه داراي ويژگي هاي : رنگ - تعداد چرخ - نام - تعداد دنده - دنده جاري - تعداد ترمز - . . .
    و رفتار هايي مانند : ترمز كردن - تعويض دنده - شتاب دادن - . . .

    اشياي يك برنامه نرم افزاري هم همانند اشياي دنياي واقعي مدل مي شوند و داراي ويژگي ها و رفتار ها هستند
    ويژگي يك شي برنامه نرم افزاري با يك يا چند متغير از نوع صحيح - اعشاري - كاراكتري يا انواع ديگر بيان ميشود .
    رفتار هاي يك شي برنامه نرم افزاري با متد (method) بيان ميشود . متد يك تابع (function)يا زير روال(procedure)
    مرتبط با شي مي باشد .
    پس يك شي يك مجموعه از متغير ها و متد ها است .
    ما مي توانيم اشياي دنياي واقعي را در برنامه خود مدل كنيم مثلا براي كنترل يك دوچرخه الكترونيكي توسط برنامه
    مي توانيم يك شي از دوچرخه را در برنامه خود داشته باشيم . و اين شي داراي متغير هايي جهت نگهداري مثلا سرعت دو چرخه
    و دنده جاري - وضعيت خاموش و روشن بودن چراغ ها
    == == = = = = = = = == = == = = = == = = = == =

    پيغام (Message ) چيست؟

    يك شي ساده به تنهايي خيلي مفيد نيست . يك شي معمولا بعنوان يك مولفه اي (component) از يك برنامه بزرگ كه شامل اشيا ي ديگري است مي باشد .
    برنامه نويس ها مي توانند با استفاده از برهم كنش و ارتباط بين اين اشيا به رفتار ها و اعمال پيچيده تري دست پيدا كنند .

    اشياي يك برنامه با فرستادن پيغام ها با يك ديگر ارتباط برقرار مي كنند . وقتي كه شي A بخواهد كه شي B يكي از متد هاي خود را اجرا كند پيغامي به شي B مي فرستد .
    == == = == = = = = = == = = =

    كلاس ( class ) چيست؟

    در دنياي واقعي اشياي زيادي وجود دارند كه از يك نوع هستند . براي مثال دوچرخه شما يكي از دوچرخه هاي زياد موجود در دنيا است . ما مي گوييم دوچرخه شما يك نمونه اي از
    كلاس دوچرخه ها است . همه دوچرخه ها داراي ويزگي ها و رفتار هاي متشابهي هستند . و مي توان آنها را در يك كلاس طبقه بندي كرد .
    پس كلاس يك مجموعه اي از متغير ها به عنوان ويژگي و متد ها به عنوان رفتار ها ي اشيايي از يك نوع
    با ايجاد يك كلاس ما مي توانيم هر تعداد نمونه از آن كلاس تعريف كنيم .
    == = = = == = == = = = == = = == = ==

    وراثت(inheritence ) چيست؟

    وراثت يك مكانيسمي است كه باعث ميشه يك كلاس مثل A ويژگي ها و رفتار هاي يك كلاس ديگري مانند B را به ارث ببرد .
    كلاس A زير كلاسي از كلاس B ناميده مي شود (Subclass) يا كلاس A مشتق شده از كلاس B . كلاس A را فرزند و كلاسB را پدر مي نامند .
    همچنين مي توانيم از يك كلاس فرزند يك كلاس ديگري را مشتق كنيم مثلا كلاس C فرزند كلاس A باشد .
    و به همين ترتيب وراثت مي تونه ادامه داشته باشه .
    كلاس C فرزند كلاس A و كلاس A فرزند كلاس B
    كلاس B پدر كلاس A و كلاس A پدر كلاس C و الا آخر . . .
    = == = = == = == = = = == =

    تعريف كلاس در سي ++

    يك كلاس با استفاده از كلمه كليدي class و به دنبال آن اسمي كه برنامه نويس براي كلاس خود انتخاب مي كند
    و سپس دو علامت براكت { } كه ساختار كلاس درون آن قرار مي گيرد و يك سميكلن در آخر تعريف مي شود

    کد:
    class ClassName 
    {
    };
    
    مثلا مي خوايم يك كلاسي از يك جعبه تعريف كنيم كه داراي طول و عرض و ارتفاع و رنگ باشد :

    کد:
    class Box
    {
    double Length, Width, Height;
    int Color;
    };
    
    قبلا گفتيم كه يك كلاس مي تونه شامل متغير هايي بعنوان ويژگي و متد هايي به عنوان رفتار باشد
    در اينجا همون طور كه در بالا ديديد در تعريف كلاس جعبه فقط از متغير استفاده كرديم تا ويژگي هاي
    آن جعبه را مشخص كنيم .و اسمي از متد و تابع آورده نشد تا رفتار آن جعبه را مشخص كند .
    حال يك كلاس ديگري تعريف مي كنيم :

    کد:
    class  Bicycle 
    {
    char  Name[10];
    int     Color;
    int    Wheel;
    int    Gear;
    int    CurrentGear;
    
    void   ChangeGear();
    };
    
    كلاس دوچرخه داراي ويژگي هاي رنگ (Color) و تعداد چرخ (Wheel) و نام (Name) و تعداد دنده (Gear ) و دنده جاري (CurrentGear) .
    و داراي متدي به نام ChangeGear براي تغيير دنده . همانطور كه ديده ميشه متد در اينجا يك تابع است .

    Method=>Function

    به هر يك از متغير ها و توابع موجود در يك كلاس عضو آن كلاس گفته مي شود .
    حال يك كلاس تعريف مي كنيم :

    کد:
    class  Box 
    {
    double   Length ,Width,Height;
    int   Color;
    double  Volum();
    };
    
    با تعريف يك كلاس بايد از آن كلاس در برنامه خود استفاده كنيم و براي استفاده از يك كلاس بايد ابتدا يك شي (Object) از آن كلاس ايجاد كنيم .

    کد:
    Box  MyBox;
    
    براي واضح شدن موضوع كد زير را نگاه كنيد :

    کد:
    include<iostream>
    using  namespace  std;
    
    [color=red]class  Box
    {
    double   Length,Width,Height;
    int   Color;
    Double   Volum();
    };
    [/color]
    int main()
    {
    [color=red]
    Box    MyBox;  // Declare Object MyBox [/color]
    int     i;
    float  Volum;
    
    . . .
    
    
    return 1;
    }
    
    جهت دسترسي به اعضاي يك شي ابتدا نام شي را نوشته و سپس يك نقطه (Point ) و سپس يك عضو شي
    مثال :
    کد:
    MyBox.Color جهت دسترسي به رنگ جعبه
    MyBox.Length دسترسي به طول جعبه 
    MyBox.Volum () دسترسي به حجم جعبه 
    
    مطلب بسيار مهم در تعريف يك كلاس وجود دارد اين است كه دسترسي به اعضاي يك كلاس را مي توانيم به سه بخش
    تقسيم كنيم . كه اين سه بخش با كلمات كليدي public و private و protected مشخص مي شوند .

    public :

    اعضايي از كلاس را در اين بخش قرار مي دهيم كه بخواهيم بيرون از كلاس به آنها دسترسي داشته باشيم . مثلا در بدنه تابع اصلي Main
    اعضايي كه در اين بخش قرار دارند اعضايي عمومي هستند كه دسترس به آنها توسط تمام توابع و كلاس هاي ديگر امكان پذير است .

    private :

    در اين بخش اعضايي را كه بخواهيم دسترسي به آنها فقط از طريق توابع موجود درون كلاس امكانپذير باشد و از خارج كلاس قابل دسترس نباشند
    تعريف مي شوند . اين اعضا خصوصي هستند و محدود به خود كلاس مي باشند .

    protected :

    اين بخش بخش محافظت شده نام دارد و در بخش مربوط به وراثت بيشتر مورد بحث قرار مي گيرد . پس تا بعد . . .

    مثال :
    مي خوايم در كلاس جعبه اعضاي طول و عرض و ارتفاع بصورت خصوصي و حجم بصورت عمومي تعريف كنيم :

    کد:
    class  Box
    {
    [color=red]public :[/color]
    double  Volum();
    [color=red]private :[/color]
    double  Length,Width,Height;
    };
    
    حال اگه يك شي از كلاس تعريف كنيم اون وقت فقط مي تونيم تابع Volum در خارج از كلاس استفاده كنيم و بقيه اعضا قابل دسترس نيستند .

    کد:
    #include<iostream>
    using  namespace  std;
    
    [color=red]class  Box
    {
    public :
    double  Volum();
    private :
    double  Length,Width,Height;
    };
    [/color]
    int main()
    {
    [color=red]
    Box    MyBox;  // Declare Object MyBox 
    [/color][color=blue]
    MyBox.Volum(); //  It   is   OK 
    
    MyBox.Length=8; // It  is   wrong 
    [/color]
    . . . 
    
    return 1;
    }
    
     
  9. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    سالك: در سايت بالا ، 3 پست ديگه(با سايز پست بالا) بايد زده بشه تا تمام مطلب نقل بشه.
    خودتان تا من نقل كنم مي توانيد از لينك بالا استفاده كنيد و بخوانيد.
    هدف من اين بود كه در اين قسمت انرژي من نگذارم و از سايتهاي ديگر استفاده كنم و بقيه مطلب را از كتابهاي انگليسي كار كنيم.من زياد زبانم خوب نيست و نمي توانستم مفاهيم پايه را خوب بگم و اين دوست عزيز هم خيلي قشنگ مطالب را بيان كرده.

    كمي كدها اشكال سينتكس داره كه خودتان رفع كنيد. چيزهاي مهمي نيست. مثل نگذاشتن ريترن و اينكلودها. مهم مفاهيم كلاس است.
    .
     
    DANTEH2010 از این نوشته تشکر کرده است.
  10. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    با سلام.
    در اينجا باز به ادامه نقل از فروم قبل مي پردازيم. از:
    http://www.hamkalam.com/forum/lofiversion/index.php/t521.html

    سالك: در نقل قبلي در پستهاي قبل اين تاپيك ،، ياد گرفتيم كه كلاس را چطور تعريف كنيم و اعضاي public و private (شامل متغير و متد(تابع) ) را شناختيم. حال به ادامه بحث توجه كنيد.

    GoodBoy:

    اگر اعضايي را در كلاس درون هيچ بخشي قرار نداديم آنها بطور پيش فرض اعضاي خصوصي در نظر گرفته خواهند شد .

    يعني كلمه كليدي Private بطور پيش فرض تمام اعضاي يك كلاس را در بر دارد و اگر بخواهيم عضوي بصورت عمومي تعريف كنيم بايد آن را در بخش public قرار بديم :

    کد:
    class  Rectangle {
       int x, y;
    [color=red] public:[/color]
       void set_values (int,int);
       int area (void);
     } rect;
    
    در اين كلاس دو عضو x و y خصوصي هستند. private حالت پيش فرض ديگه نيازي نيست اونو بنويسيم. در بخش public هم كه دو متد از نوع عمومي تعريف كرديم .

    set_value براي مقدار دهي به مقادير xو y
    area هم براي بدست آوردن مساحت

    همون طور كه ديده ميشه دو عضو كلاس دو تابع هستند يكي براي مقدار دهي به متغير ها و ديگري براي محاسبه مساحت

    rect هم كه يك شي از اين كلاس .

    = = = = = = == = == ==
    براي تعريف اين توابع دو روش هست :
    يكي اينه كه اين توابع رو درون كلاس تعريف كنيم كه به اين تعريف محلي يا inline گفته ميشه .
    روش دوم اينه كه در خارج از كلاس و البته بعد از تعريف كلاس توابع رو تعريف كنيم به اين تعريف عمومي يا global گفته ميشه .

    روش محلي :

    کد:
    class  Rectangle {
    int x, y;
    public:
    void set_values (int  a , int b ) 
    {
    x=a; y=b; 
    }
    int area (void)
    {
    return (x*y);
    }
    };

    حال يك مثال كامل كه قابل اجرا هست را مي نويسم :
    کد:
    #include <iostream.h>
    
    [color=red]class  Rectangle {
    int x, y;
    public:
    void set_values (int  a , int b ) 
                {
    x=a; y=b; 
                }
    int area (void)
          {
    return (x*y);
          }
                             };[/color]
    
    int main () {
     [color=red]Rectangle   rect ,  rectb;[/color]
    [color=blue] rect.set_values (3,4);
     rectb.set_values (5,6);[/color]
     cout << "rect area: " <<  [color=blue]rect.area()[/color] << endl;
     cout << "rectb area: " << [color=blue] rectb.area()[/color] << endl;
    }
    ===========روش دوم============

    روش دوم تعريف متد هاي يك كلاس بصورت Global يعني در خارج از كلاس است . در اين روش به همان صورتي كه متد درون كلاس تعريف مي شود هست ولي بايد به همراه متد نام كلاس نيز آورده شود و اين به اين خاطر است كه متد كلاس از بقيه توابع كه بصورت سراسري تعريف مي شوند جدا شده و قابل تشخيص باشد . براي اتصال نام كلاس به متد از عملگر اسكوپ استفاده مي شود :):)

    مثال:
    کد:
    #include <iostream.h>
    
    [color=red]class   Rectangle {
       int x, y;
     public:
       void set_values (int,int);
       int area (void) {return (x*y);}
    };[/color]
    
    [color=green]void  Rectangle[/color][color=red]::[/color][color=green]set_values (int a, int b) {
     x = a;
     y = b;
    }[/color]
    
    int main () {
     [color=red]Rectangle rect;[/color]
    [color=blue] rect.set_values (3,4);[/color]
     cout << "area: " << [color=blue]rect.area()[/color];
    }
    متد area درون كلاس inline تعريف شده و متد set_value در خارج از كلاس Global تعريف شده است .

    يك مثال ديگه:

    کد:
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    [color=red]class student {
    char name[30];
    
    public:
    void putname(char *str);
    void getname(char *str);
    
    private:
     int grade;
    
    public:
    void putgrade(int g);
    int getgrade();
    };
    [/color]
    [color=green]void student[/color][color=red]:: [/color][color=green]putname(char *str) {
    strcpy(name, str);
    }
    
    void student[/color][color=red]:: [/color][color=green]getname(char *str) {
    strcpy(str, name);
    }
    
    void student[/color][color=red]:: [/color][color=green]putgrade(int g) {
    grade = g;
    }
    
    int student[/color][color=red]:: [/color][color=green]getgrade() {
    return grade;
    }[/color]
    int main() {
    [color=red]student x;[/color]
    
    char name[50];
    
    [color=blue]x.putname("GoodBoy");
    x.putgrade(5);
    
    x.getname(name); [/color]
    cout<<name<<" got "<<[color=blue]x.getgrade()[/color]<<" from OOP."<<endl;
    return 0;
    }
    goodboy:
    در پست بعدي اين كد رو تجزيه و تحليل مي كنم ! پس تا بعد . . .
    .
     
  11. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    شرح برنامه پست قبل:

    کد:
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    اين سه خط كه تعريف دو كتابخانه يكي ورودي خروجي و ديگري كار با رشته هاست .
    سالك: كامپايلر ايشان(goodboy ) ويژوال سي است. اين قسمتها را خودتان تبديل كنيد.

    کد:
    class student {
    char name[30];
    
    public:
    void putname(char *str);
    void getname(char *str);
    
    private:
     int grade;
    
    public:
    void putgrade(int g);
    int getgrade();
    };
    اين هم تعريف يك كلاس بنام student داراي اعضاي زير است :
    اول name اسم دانش آموز كه private است.
    دوم(چند خط پايين تر) grade ، نمره دانش آموز كه باز private است.

    متد putname عمومي public براي مقدار دهي به name در خارج كلاس.
    متد getname عمومي public براي دسترسي به مقدارname خارج از كلاس.

    متد putgrade عمومي public براي مقدار دهي به grade در خارج از كلاس.
    متد getgrade عمومي public براي دسترسي به grade خارج كلاس.

    همونطور كه مشاهده مي كنيد بخش هاي خصوصي و عمومي دو بار تعريف شدند يعني در دو جا از كلمه كليدي public استفاده كرديم
    هيچ گونه محدوديتي در استفاده از تعداد بخش هاي عمومي و خصوصي نيست و ما مي توانيم بر اساس بزرگي كلاس اون رو به بخش هاي
    كوچيك تر و قابل فهم تر تقسيم كنيم .

    کد:
    void student::putname(char *str) {
    strcpy(name, str);
    }
    با استفاده از تابع داخلي strcpy موجود در كتابخانه cstring براي مقدار دهي متغير name استفاده كرديم.


    کد:
    void student::getname(char *str) {
    strcpy(str, name);
    }
    اين برعكس متغير name درون str كپي مي شود و str هم كه درون برنامه قابل دسترس است.

    کد:
    void student::putgrade(int g) {
    grade = g;
    }
    مقدار دهي به متغير grade.

    کد:
    int student::getgrade() {
    return grade;
    }
    جهت دسترسي به متغير grade در خارج كلاس لازم است كه اين متد مقدار grade رو برگردونه.

    کد:
    student x;
    
    در تابع اصلي x يك شي و نمونه اي از كلاس student تعريف مي شود .

    کد:
    x.putname("GoodBoy");
    x.putgrade(5);
    
    در اين قسمت با استفاده از دو متد عمومي مقدار دهي اوليه متغير هاي grade و name انجام ميشه.

    کد:
    x.getname(name);
    cout<<name<<" got "<<x.getgrade()<<" from OOP."<<endl;
    
    در پايان جهت دسترسي به دو متغير خصوصي از دو متد عمومي استفاده ميشه !
     
  12. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    contrucrors and destrustors
    سازنده ها و مخرب ها

    اشيا Objects معمولا نيازمند به مقدار دهي اوليه متغير ها و تخصيص حافظه پويا در زمان شكل گيري هستند .
    يك كلاس مي تواند شامل يك تابعي بنام سازنده cuonstructor كه مي تواند اين عمل مقدار دهي اوليه رو در زمان تشكيل شي انجام دهد .
    اين تابع در واقع يك متد بسيار ويژه است چرا ؟ چون با ايجاد يك شي اين متد بطور خود كار فراخواني شده و اجرا مي شود . نكته جالب توجه اينجاست
    كه اين سازنده هيچ مقداري رو برنمي گردونه و از كلمه كليدي void هم در تعريف آن استفاده نمي شه .
    نكته ديگر كه اين تابع رو ويژه مي سازد اين است كه نام اين تابع با نام كلاس يكي است ! جالبه نيست ؟؟

    کد:
    class Rectangle {
       int width, height;
     public:
       Rectangle ();
       int area (void) {return (width*height);}
    };
    
    Rectangle::Rectangle () {
     width = 10;
     height = 20;
    }
    در بالا كلاسي بنام Rectangle تعريف كرديم كه يك سازنده بنام Rectangle داره . بعد از كلاس اين سازنده رو تعريف كرديم
    كاري كه انجام مي ده اينه كه تمام اشياي ساخته شده از اين كلاس مستطيل هايي به ابعاد 10 در 20 هستند .
    حال تابع اصلي رو مي نويسم :

    کد:
    int main () {
     Rectangle   rect;
     
     cout << "rect area: " << rect.area() << endl;
     return 1;
    }
    = = = = = = = = = = = = = =
    سازنده يك تابع است و همانند ديگر توابع ميتونه آرگومانهايي به عنوان ورودي بگيره . در اين حالت موقع تعريف يك شي از كلاس بايد
    به همراه مقادير ورودي صورت بگيره . مثال :

    کد:
    #include <iostream.h>
    
    class  Vector {
     public:
       int x,y;
       Vector (int,int);
    };
    
    Vector::Vector (int a, int b) {
     x = a;
     y = b;
    }
    
    int main () {
    [color=red] Vector   c (3,1);[/color]
     
     cout << c.x << "," << c.y;
     return 0;
    }
    يك كلاس بنام Vector كه داراي سازنده اي با دو ورودي از نوع عدد صحيح . در تابع اصلي وقتي كه مي خوايم يك شي از اين كلاس
    ايجاد كنيم بايد به همراه نام شي درون پرانتز دو عدد صحيح به عنوان ورودي بياوريم .

    = = = = = = = = =
    يك مفهوم ديگري اين كه يك كلاس مي تونه داراي چند ين سازنده باشد . مثلا يكي بدون آرگومان و يكي ديگه داراي چند آرگومان باشد
    به اين عمل Overload سازنده گفته ميشه ( دوباره تعريف كردن يا دوباره ساختن)

    مثال فوق رو با دو سازنده در زير مي بينيم :

    کد:
    #include <iostream.h>
    
    class  Vector {
     public:
       int x,y;
       Vector ();
       Vector (int,int);
       };
    
    [color=blue]Vector::Vector (int a, int b) {
     x = a;
     y = b;
    }[/color]
    
    [color=red]Vector::Vector () {
     x = 10;
     y = 20;
    }[/color]
    
    int main () {
     Vector a (3,1);
     Vector c;
     
     cout << c.x << "," << c.y;
     cout << a.x << "," << a.y;
     return 0;
    }
     
  13. avajang.com .leftjee.ir.right
  14. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    Destructor
    مخرب

    مخرب تابعي ديگر كه عمل مخالف سازنده انجام مي دهد . گفتيم كه سازنده زماني كه يك شي از كلاسي ايجاد شد بطور خودكار فراخواني و اجرا مي شود و برنامه نويس نيازي نيست كه آن را در بدنه تابع فراخواني كند .
    مخرب نيز به همين صورت است . منتها قبل از اينكه شي از بين برود اين مخرب بطور خودكار فراخواني و اجرا مي شود . اين مخرب نيز يك تابعي است هم نام با كلاس ولي با يك علامت مد ~ در ابتداي آن قرارردارد . كه دليل بر مخرب بودن آن است .
    پس تا اينجا متوجه شديم كه سازنده بطور خودكار زمان ايجاد يك شي از كلاس فراخواني و اجرا مي شود و كار اين سازنده مقدار دهي اوليه و تخصيص حافظه مي باشد،
    برعكس مخرب قبل از نابودي شي فراخواني و اجرا شده و كارش هم آزاد سازي حافظه اي كه سازنده تخصيص داده بود .

    به مثال زير دقت كنيد :

    کد:
    #include <iostream.h>
    
    class Rectangle {
       int *width, *height;
     public:
       Rectangle (int,int);
       ~Rectangle ();
       int area (void) {return (*width * *height);}
    };
    
    Rectangle::Rectangle (int a, int b) {
     width = new int;
     height = new int;
     *width = a;
     *height = b;
    }
    
    [color=red]Rectangle::~Rectangle () {
     delete width;
     delete height;
    }[/color]
    
    int main () {
     Rectangle rect (3,4), rectb (5,6);
     cout << "rect area: " << rect.area() << endl;
     cout << "rectb area: " << rectb.area() << endl;
     return 0;
    }


    براي تخصيص حافظه به يك اشاره گر در سي ++ از عملگر new و براي آزاد سازي حافظه اختصاص داده شده از عملگر delete استفاده ميشود .
    در ضمن مخرب نه مقداري ميگيره و نه مقداري رو برمي گردونه .
     
  15. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    اشاره گر به كلاس

    اشاره گر به يك كلاس همانند ديگر اشاره گرها بايد بعد از تعريف با استفاده از عملگر new تخصيص حافظه به آن صورت گيرد و در اين حالت دسترسي به اعضاي آن بجاي عملگر نقطه Point از عملگر اشاره گر a -> b استفاده ميشود :

    کد:
    class CRectangle {
       int width, height;
     public:
       void set_values (int, int);
       int area (void) {return (width * height);}
    };
    
    void CRectangle::set_values (int a, int b) {
     width = a;
     height = b;
    }
    
    int main () {
     CRectangle [color=blue]a[/color],[color=red] *b, *c;[/color]
     CRectangle [color=DarkOrange]* d = new CRectangle[2];[/color]
     [color=red]b= new CRectangle;
     c= &a;[/color]
     [color=blue]a.set_values (1,2);[/color]
     [color=red]b->set_values (3,4);
     d->set_values (5,6);[/color]
    [color=DarkOrange] d[1].set_values (7,8);[/color]
     cout << "a area: " <<[color=blue] a.area()[/color] << endl;
     cout << "*b area: " << [color=red]b->area()[/color] << endl;
     cout << "*c area: " << [color=red]c->area()[/color] << endl;
     cout << "d[0] area: " << [color=DarkOrange]d[0].area()[/color] << endl;
     cout << "d[1] area: " << [color=DarkOrange]d[1].area()[/color] << endl;
     return 0;
    }

    .
     
  16. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    كلمه كليدي this

    اين كلمه كليدي درون يك كلاس مورد استفاده قرار گرفته و شيي از كلاس را كه در حال اجراست را نشان مي دهد اين يك اشاره گر است كه داراي آدرس يك شي از كلاس است همون شي كه در آن لحظه در حال اجراست .

    کد:
    #include <iostream.h>
    
    class CDummy {
     public:
       int isitme (CDummy& param);
    };
    
    int CDummy::isitme (CDummy& param)
    {
     if (&param == [color=red]this[/color]) return 1;
     else return 0;
    }
    
    int main () {
     CDummy a;
     CDummy* b = &a;
     if ( b->isitme(a) )
       cout << "yes, &a is b";
     return 0;
    }
    يا يك مثال ديگه وقتي كه مقدار برگشتي يك متد كلاس باشد.

    کد:
    CVector& CVector::Copy ( CVector&  param)
    {
     x=param.x;
     y=param.y;
     return *[color=red]this[/color];
    }
     
  17. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    كلمه كليدي friend

    همونطور كه قبلا ديديم سه بخش دسترسي به اعضاي يك كلاس وجود دارد . public و private و protected
    و دو بخش private و protected از خارج كلاس قابل دسترسي نبودند ما مي توانيم با استفاده از كلمه كليدي friend اين دو بخش رو قابل دسترسي كنيم . در مثال زير دقت كنيد كه تابع Duplicate بصورت friend تعريف شده است توجه كنيد كه تابعDuplicate به عنوان يك تابع external تعريف شده و نه يك متدي از كلاس در واقع كلمه كليدي friend ما را قادر مي سازد كه يك تابع خارجي رو درون كلاس طوري تعريف كنيم كه قادر به استفاده از اعضاي خصوصي كلاس باشيم . و همچنين در تابع اصلي به طرز فراخواني اين تابع دقت كنيد . مي دانيم كه يك تابع وقتي كه عضو يك كلاس باشد در زمان فراخواني بايد به همراه نام شي ايجاد شده از كلاس بيايد ولي اين تابع ما عضو كلاس نيست .

    کد:
    #include <iostream.h>
    
    class CRectangle {
       int width, height;
      [color=red] friend CRectangle duplicate (CRectangle);[/color]
     public:
       void set_values (int, int);
       int area (void) {return (width * height);}
    };
    
    void CRectangle::set_values (int a, int b) {
     width = a;
     height = b;
    }
    
    [color=red]CRectangle duplicate (CRectangle rectparam)
    {
     CRectangle rectres;
     rectres.width = rectparam.width*2;
     rectres.height = rectparam.height*2;
     return (rectres);
    }[/color]
    
    int main () {
     CRectangle rect, rectb;
     rect.set_values (2,3);
     cout << rect.area()<<endl;
     [color=red]rectb = duplicate (rect);[/color]
     cout << rectb.area()<<endl;
    }
    به همين صورت كه يك تابع از نوع friend تعريف كرديم مي تونيم يك كلاسي رو درون يك كلاس ديگر از نوع friend تعريف كنيم تا بتواند از اعضاي خصوصي آن كلاس استفاده كند :

    کد:
    #include <iostream.h>
    
    [color=green]class CSquare;[/color]
    
    class CRectangle {
       int width, height;
     public:
       int area (void)
         {return (width * height);}
       void convert ([color=blue]CSquare a[/color]);
    };
    
    [color=green]class Csquare[/color] {
     private:
       int side;
     public:
       void set_side (int a)
         {side=a;}
      [color=red] friend class CRectangle;[/color]
    };
    
    void CRectangle::convert (CSquare a) {
     [color=red]width = a.side;
     height = a.side;[/color]
    }
     
    int main () {
     CSquare sqr;
     CRectangle rect;
     sqr.set_side(4);
     rect.convert(sqr);
     cout << rect.area();
     return 0;
    }

    در اينجا دو كلاس تعريف كرديم يكي CRectangle و ديگري CSquare كه درون كلاس CSquare كلاس CRectangle رو صورت friend تعريف كرديم . اين تعريف باعث ميشه كه كلاس CRectangle بتواند از اعضاي كلاس CSquare استفاده نمايد . به مثال بالا دقت كنيد در حالت عادي كلاس CRectangle نمي تواند از اعضاي خصوصي كلاس CSquare مثل Side استفاده كند اما با كلمه كليدي friend همان طور كه در تعريف تابع convert ديده ميشه از اعضاي خصوصي كلاس CSquare استفاده شده است .
     
  18. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    Overloading operators

    سي ++ تنظيماتي رو براي استفاده از عملگرهاي استاندارد بين كلاس ها علاوه بر نوع داده هاي پايه جا سازي كرده است .
    براي مثال :

    کد:
    int a,b,c;
    a=b+c;
    
    كاملا معتبر است . و همه متغير ها از نوع داده پايه هستند . Fundamental Type
    اما واسه داده هاي از نوع مثلا ساختار اين گونه عمل جمع نامعتبر است :

    کد:
    struct { char product [50]; float price; } a, b, c;
    a = b + c;
    
    البته عمل انتساب = يك كلاس يا ساختار به كلاس يا ساختار ديگر از همان نوع معتبر است و تنها چيزي كه باعث خطا مي شود اعمالي مانند جمع است كه اين عمل بين نوع هاي داده اي غير پايه نامعتبر است .

    اما با تشكر از سي ++ كه با اوود لود كردن عملگرها اين امكان و اجازه رو به ما داده است . در اينجا ليستي از عملگرهايي رو كه اجازه اوود لود كردن آنها داريم مي بينيم :

    کد:
    +    -    *    /    =    <    >    +=   -=   *=   /=   <<   >>
    <<=  >>=  ==   !=   <=   >=   ++   --   %    &    ^    !    |
    ~    &=   ^=   |=   &&   ||   %=   []   ()   new  delete
    
    واسه اوور لود كردن يك عملگر تنها كاري كه بايد انجام دهيم تعريف يك تابع درون كلاس بعنوان عضوي از كلاس است.
    نام اين تابع بايد از كلمه كليدي operator و به دنبال آن علامت عملگر كه مي خواهيم اوور لود كنيم تشكيل شود همانند زير :

    کد:
    type  operator sign (parameters);
    
    در اينجا يك مثالي واسه استفاده از عملگر جمع بين كلاس ها ميارم . اين كلاس يك بردار رو تعريف مي كنه و جمع بين بردار ها كه همه مي دونن چطوريه ! مولفه هاي اول با هم جمع ميشن و مولفه هاي دوم با هم !

    کد:
    #include <iostream.h>
    
    class CVector {
     public:
       int x,y;
       CVector () {};
       CVector (int,int);
       CVector operator + (CVector);
    };
    
    CVector::CVector (int a, int b) {
     x = a;
     y = b;
    }
    
    CVector CVector::operator+ (CVector param) {
     CVector temp;
     temp.x = x + param.x;
     temp.y = y + param.y;
     return (temp);
    }
    
    int main () {
     CVector a (3,1);
     CVector b (1,2);
     CVector c;
     c = a + b;
     cout << c.x << "," << c.y;
     return 0;
    }
    همون طور كه مشاهده كرديد اوور لود كردن يك تابعي است و عضوي از كلاس كه مقداري رو مي گيره و مقداري رو برمي گردونه . ما مي تونيم به دو روش زير عمل جمع بين داده هاي كلاس انجام بديم :

    کد:
    c = a + b;
    c = a.operator+ (b);
    
    آموزشهاي زيباي جناب GOODBOY تمام شد.
    درود.
     
  19. saalek

    saalek مدیر بازنشسته

    تاریخ عضویت:
    ‏24 می 2005
    نوشته ها:
    654
    تشکر شده:
    53
    محل سکونت:
    در پاي كوهپايه ها
    براي راحتي بيشتر ميشه ((تعريف كلاس)) را در يك فايل header قرار داد.
    کد:
    #ifndef CAR_H
    #define CAR_H
    
    class Car {
    public:
    
    protected:
    
    };
    #endif
    
    به آن class header file مي گوييم.
    و بعد مثلا در برنامه(فايل) اصلي داريم:

    کد:
    // اينكلود كردن كلاس هيدر فايل مربوطه
    [color=red]#include "Car.h"[/color]
    
    void f()
    {
      Car a;                                            
      Car b(100, 73);                                   
    
      // ...
    }
    
    int main()
    {
    
      f();
    }
    
    يا :

    کد:
    #include "Car.h"                                  
    
    void f()
    {
      Car a;                                            
      a.startEngine();                                  
      a.tuneRadioTo("AM", 770);                         
    [color=red]}[/color]                                                   
    
    int main()
    {
      f();
    }
    
    در برنامه بالا در تابع f() يك شي car خلق شده و دو member آن مورد استفاده قرار گرفته اند. و در محل كروشه قرمز اين شي destroy يعني نابود مي شود.

    همچنين مرگ اشيا را در كروشه هاي قرمز برنامه زير داريم:

    کد:
    #include "Car.h"
    
    void f()
    {
      Car a;
    
      for (int i = 0; i < 10; ++i) {
        Car b;                                          
        // ...
      [color=red]}[/color]      // Each iteration's [color=red]b[/color] dies here                                           
    
      // ...
    [color=red]}[/color] //    Object [color=red]a[/color] dies here                                               
    
    int main()
    {
      f();
    }

    از كتاب C++ FAQs, Second Edition .
     
  20. A.S.Roma

    A.S.Roma کاربر تازه وارد

    تاریخ عضویت:
    ‏9 می 2006
    نوشته ها:
    24
    تشکر شده:
    0
    با سلام
    خدمت تمامي دوستان به ويژه saleek مدير محترم بخش.
    همين جا درباره تاپيك نحوه ارسال مقادير به توابع از تمامي دوستاني كه آنجا اظهار نظر فرمودند كما تشكر را دارم. ( واقعا بحث كاملي شد و به شخصه خيلي استفاده كردم .)
    و اما دو بحث ديگر :
    1- اشاره گر This
    2- وراثت

    مشخصا اين دو بحث درباره برنامه نويسي شي گرا است .
    از دوستانه خواهش مي كنم اين دو بحث را نيز به كنفرانس بگذارند تا يك نتيجه گيري كلي انجام دهيم.
    از اشاره گر this به شخصه چيزي نفهميدم.!
    با تشكر
     
  21. MahdiΩ

    MahdiΩ کاربر تازه وارد

    تاریخ عضویت:
    ‏27 ژانویه 2006
    نوشته ها:
    324
    تشکر شده:
    0
    سلام
    اشاره گر this به خود شیء اشاره میکنه.
    مثلاً توی توابع عضو کلاس هر جا نیاز به دسترسی به خود کلاس بود میتونیم (باید) از this اشاره بکنیم.
    مثلا اگه m یک عضو داده ای کلاس باشه ، درون توابع عضو میتونیم هم به صورت ساده m بهش دسترسی داشته باشیم و هم به صورت this نقطه m
    یک کاربرد دیگه موقعی هست که یک تابع عضو کلاس نیاز داره یک شیء از کلاس رو به عنوان خروجی برگردونه در این موقع با استفاده از return اشاره گر this رو ارسال میکنه.

    وراثت هم بحـثـش خیلی خیلی عمیق و طولانی هست!
     
zarpopخرید بک لینک عسل طبیعی و گرده گل ایرانی