مشاهده نسخه کامل
: آموزش ++C
sin2x=2sinxcosx
12-07-2009, 10:11
سلام ...
به انجمن هاي برنامه نويسي ديگه (دلفي و ويژوال بيسيک و ويبي.نت ) که مي رفتم ديدم هر کدوم يه تاپيک دارن در مورد آموزش زبان برنامه نويسي اون انجمن . گفتم خوب بهتره انجمن C هم يکي داشته باشه .
من از امروز ان شاءالله شروع مي کنم . بهتره دوستاي ديگه هم که در مورد Syntax اين زبان مشکل دارن سوالاتشونو تو اين تاپيک مطرح کنن و وقتي هم که مي خوان در مورد مشکل برنامه اي که نوشتن راهنمايي بخوان اون موقع تاپيک جديد ايجاد کنن .
اميدوارم به کمک دوستان به تاپيک مفيدي تبديل بشه ... :20:
sin2x=2sinxcosx
12-07-2009, 10:58
بدون هيچ حاشيه اي شروع مي کنم .
فقط قبلش اينکه بحث راجع به کلاس ها رو به آخر موکول مي کنم . فعلا بيشتر روي ساخت يافته ( Structured ) بحث مي کنم .
نکاتي هم که مهم تر هستن با رنگ قرمز نشون ميدم .
سعي مي کنم مطالب رو به مرور با گذاشتن يکي دو تا فايل PDF ، منظم تر کنم .
ضمنا از دوستان محترم هم درخواست دارم از کوچکترين اشکال علمي يا املايي چشم پوشي نکرده و گوشزد کنند . :20:
فصل اول : مباحث پايه اي ++C
خوب مي خوايم برنامه بنويسيم . به زبان ++C ! تقريبا هر برنامه اي تو ++C ، چه به صورت ساخت يافته نوشته بشه و چه به صورت شي گرا ، حداقل از يک تابع تشکيل ميشه که يکيشون دقيقا اسمش بايد main باشه . اجراي برنامه از تابع main شروع ميشه . يعني کامپايلر مياد و دستورات داخل اين تابع رو خط به خط اجرا مي کنه و اين تابع هست که تابع و کلاس هاي ديگه رو براي انجام کارهاي ديگه فراخواني مي کنه .
خوب حالا تابع چيه ؟
اين بمونه براي فصول بعد .... :20:
مي خوايم سريعا اولين برنامه مونو بنويسيم . پس همون طوري که اشاره شد تابع main مون رو مي نويسيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين تعريف تابع main هست . کلمه int ميگه که نوع داده برگشتي اين تابع int هستش . ( در مورد نوع داده بعدا بحث ميشه . ) پرانتزهاي باز و بسته ليست پارامترهاي تابع رو نشون ميدن . ( پارامتر هم بمونه براي چند فصل بعد . چون ما فعلا راجع به تابع main بحث مي کنيم و اين ليست پارامتر ها براي main هميشه خالين . ) اين ليست پارامتر خالي به ما ميگه اين تابع براي انجام کارش هيچ داده يا اطلاعاتي رو دريافت نمي کنه . نوع داده برگشتي هم بمونه براي بعد ولي فقط اينو بدونين که هميشه سعي کنين شکل تعريف تابع main تون اينجوري باشه .
حالا ما دستوراتمونو تو تابع main مي نويسيم .
به عنوان مثال مي خوايم يه متني رو چاپ کنيم . کافيه تو تابع main بنويسيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
هر عبارتي که داخل " " باشه تو خروجي ( که به طور پيش فرض صفحه نمايش هست ) چاپ ميشه .
اين cout چيه ؟ اين cout يک شي متعلق به کلاس ostream هست که کار چاپ اطلاعات تو صفحه نمايش رو انجام ميده .
ostream چيه ؟ اين بمونه براي آخر آخر .... :31: شايد هم نرسيديم ... :20:
>> يه عملگر گفته ميشه که طرف راست خودش رو تو cout قرار ميده و اين کار باعث ميشه که عبارت طرف راستي تو خروجي چاپ بشه . الگوريتم کار براي چاپ اطلاعات تو خروجي در کتابخانه استاندارد ++C وجود داره . بنابراين ما بايد اينو به کامپايلر هم نشون بديم . اين کار با قرار دادن عبارت زير در اول برنامه انجام ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ما گفتيم که از يک شيء به نام cout که متعلق به فضاي نام std هست هم استفاده کرديم . بنابراين اينو هم بايد به کامپايلر گفت . با اين دستور :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
چون گفتيم قبل از تابع main يه int بذارين ، آخر تابع main هم يدونه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بذارين که معلوم بشه اجراي برنامه به پايان رسيده .
بنابراين برنامه مون به شکل زير در مياد :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
خروجي برنامه اين ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
sin2x=2sinxcosx
13-07-2009, 10:31
خوب ادامه مطالب :
ديديم که مي تونيم با استفاده از شيء cout که معمولا به صفحه نمايش وصله يه چيزي رو تو خروجي چاپ کنيم . حالا برعکس اون اينکه از ورودي يه چيزي بگيريم از cin استفاده مي کنيم . cin هم به طور معمول به صفحه کليد وصله . cin يه مقداري رو از صفحه کليد مي گيره و تو يه متغير ذخيره مي کنه . حالا متغير چيه ؟
متغير چيزيه که تغيير مي کنه . برنامه نويسان از متغيرها استفاده مي کنن تا مقاديرشون رو طي اجراي برنامه تو اونا ذخيره کنن . هر متغير يه نوع داده داره ، يه مقدار ، يه اسم و يه اندازه .
انواع داده اصلي ++C عبارتند از :
int, char, float, double .
int ، اعداد صحيح رو نگه مي داره . تا اونجايي که يادمه از منفي دو ميليارد تا مثبت دو ميليارد . 4 بايت حافظه اشغال مي کنه .
char ، کاراکتر ذخيره مي کنه . ( فقط يک کاراکتر ) . 1 بايت هم حافظه مي گيره .
توضيح : تو ++C ، يه نوع داده هم اضافه شده به اسم string که مي تونه دنباله اي از کاراکترها يا همون رشته ها رو تو خودش ذخيره کنه که جزو انواع داده اي اصلي محسوب نمي شه . ( پرانتز بسته ! )
float هم اعداد اعشاري رو مي تونه تو خودش ذخيره کنه . ايشون هم 4 بايت حافظه مي گيرن .
double هم مثل float ولي با کمي Range بيشتر . ( کمي بيشتر از کمي :46: ) مي تونين دو برابر فرض کنين چون 8 بايت حافظه مي گيره .
خوب براي تعريف يه متغير ، اول نوع داده بعد اسم متغير و بعد سمي کالن ( ; ) .
راستي يادم رفت بگم که تو ++C براي اينکه بگيم يه دستوري تموم شده آخرش يه سمي کالن مي ذاريم . يه استثناء وجود داره که اون هم دستورهاي پيش پردازنده هستن . همون include ها .
مثلا مي خوايم يه متغير از نوع int به اسم num بگيريم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه متغير يا مقدارشو از صفحه کليد مي گيره و يا توسط دستورهاي انتساب يا assignment .
حالت اول :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در اينجا با همون cin اي که قبلا اشاره شد يه مقداري از صفحه کليد گرفته ميشه و تو num ذخيره ميشه .
حالت دوم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در اينجا هم num مقدار 124 رو ميگيره .
نکته : هر متغيري که تعريف ميشه ، قبل از اينکه مقداري توش گذاشته بشه يه مقدار زايد به خودش ميگيره . مثل 858993460 - . پس حتما قبل از اينکه يه همچين مقداري توش جاي بگيره خودتون يه مقداري مثل صفر بهش بدين .
براي جمع و ضرب و اينا هم فرض کنين num1 و num2 دو متغير از نوع int هستن . براي جمع و تفريق و ضرب و تقسيم به ترتيب :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تو ++C يه عملگر هم داريم که باقيمانده تقسيم دو عدد صحيح ( int ) رو به ما ميده . اون هم % هستش .
مثلا اگه num1 برابر 23 باشه و num2 برابر 7 ، 7 % 23 ميشه 2 :20: .........
راستي num1 / num2 هم ميشه 3 . نه 3.28 . چرا ؟ چون هر دو عدد صحيح بودن و جواب هم بايد عدد صحيح باشه .
اگه هر دو float يا double بودن چي ؟
جواب : بله اون وقت ميشد 3.28 :46: .
براي مقايسه هم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
که به ترتيب :
بزرگتر
بزرگتر يا مساوي
کوچکتر
کوچکتر يا مساوي
برابر
نابرابر
سلام خیلی ممنون،
بهتره اول از شیء گرایی شروع کنیم
sin2x=2sinxcosx
13-07-2009, 11:57
سلام خیلی ممنون،
بهتره اول از شیء گرایی شروع کنیم
يعني شما ميگين اين طوري بهتره ؟
من گفتم اول از ساخت يافته شروع کنيم که مطالب براي تازه کارها زياد پيچيده نباشه .
خوب پس اگه صلاح باشه من بقيه رو با مقدمه اي از کلاس ها و اشياء پي مي گيرم . با کمک شما دوستان عزيز . :20:
sin2x=2sinxcosx
14-07-2009, 13:37
سلام .
در مورد کلاس ها و اشياء و برنامه نويسي شيء گرا
در برنامه نويسي ساخت يافته ، واحد برنامه نويسي تابع است . يعني هر برنامه ساخت يافته از يک يا چند تابع تشکيل مي شوند .
در برنامه نويسي شيءگرا ، واحد برنامه نويسي ، قطعاتي به نام کلاس هستند . يعني هر برنامه شيءگرا از يک يا چند کلاس تشکيل مي شود .
هر کلاس رو به قول آقاي ديتل ميشه يه نقشه فرض کرد . فرض کنين يه کلاسي براي ماشين نوشتيم . ( يعني نقشه ماشين ) . اين کلاس رو مي نويسيم تا بتونيم بعدا از اين کلاس ( نقشه ) يه ماشين درست کنيم . به اين ماشينه ميگيم شيء . يعني هر چيزي که از کلاس ( نقشه ) نمونه سازي بشه ، شيء ناميده ميشه .
کلاس يا نقشه ماشين ما ، تعدادي خصيصه يا attribute و تعدادي رفتار يا behavior داره . مثلا از خصيصه ها ميشه به رنگ ، تعداد در ، تعداد چرخ و ... اشاره کرد . رفتار ها هم مثلا سرعت گرفتن ، ايستادن ، تک چرخ زدن :31: و ... . براي هر رفتار يک دستگيره يا handle در نظر گرفته ميشه که کاربر بتونه با اون دستگيره اين اعمال رو انجام بده . مثلا تو ماشين واقعي براي سرعت گرفتن ، دستگيره پدال گاز در نظر گرفته شده و کاربر يا همون راننده ماشين مي تونه با فشار پا بر روي اون ، ماشين رو وادار به سرعت گرفتن کنه . تو نقشه ماشين يا همون کلاس ، همچين دستگيره اي وجود نداره . فقط الگوريتم اون کار نوشته شده . بنابراين براي تست بايد ما يه ماشين يا شيء از اون کلاس يا نقشه داشته باشيم و پدال گاز مربوط به اونو فشار بديم .
يه مثال از کلاس مي زنم و مطالبي که گفتم تو اون مشخص مي کنم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
براي تعريف کلاس از کلمه کليدي class استفاده مي کنيم و بعد از اون اسم کلاس . با آکلاد باز بدنه کلاس رو مشخص مي کنيم . کلمه :public رو مي بينين . اين کلمه نشون ميده که توابع move و stop و jump حالت عمومي دارن و هر جايي خارج از کلاس مي شه بهش به طور مستقيم دسترسي داشت . يعني کاربر مي تونه تابع move مربوط به يک شيء از کلاس رو اجرا کنه تا ماشين سرعت بگيره . سه تابع اشاره شده ، توابع عضو کلاس ناميده ميشن . بعد کلمه private رو مي بينين . اين کلمه هم نشون ميده که متغيرهاي color و اون دو تاي ديگه حالت خصوصي دارن و فقط در داخل کلاس ميشه بهش دسترسي داشت . يعني قرار نيست کاربر بخواد به طور مستقيم بياد و تعداد درهاي يک ماشين رو عوض کنه . ( در عمل هم همچين کاري غير منطقيه ) بنابراين به طور خصوصي تعريف ميشن . پايان کلاس با يه آکلاد بسته به همراه ; تموم مي شه . البته فرض ميشه که توابع move و stop و jump قبلا تعريف شدن . حالا ميايم تو تابع main اين کارارو مي کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ماشين حرکت مي کنه ، مي ايسته ، مي پره :46: .
به اون سه تا تابع ميگيم رفتار ( behavior )
به اون سه تا متغير که خصوصيات ماشين رو مشخص مي کردن مي گيم خصيصه ( attribute ) .
تو تابع main يک شيء به نام c ( يک ماشين به نام c ) ايجاد کرديم و از اون سه تا دستگيره براي انجام کارامون استفاده کرديم .
خیلی جالب بود. من حدودا 15 سال هست که مرتبا با مفاهیم Object Oriented کار میکنم اما توضیحی که دادی خیلی روشن بود. ممنون.
sin2x=2sinxcosx
16-07-2009, 09:54
ادامه ....................
توابع عضو يا همون توابعي که داخل يک کلاس تعريف شدن عملياتي رو روي داده هاي عضو ( يا همون داده ها و متغيرهايي که در داخل کلاس تعريف شدن ) انجام مي دن . تمام توابع عضو کلاس به طور مستقيم مي تونن به داده هاي عضو دسترسي داشته باشن و مقداراشونو تغيير بدن .
مطلب ديگه اي که در مورد کلاس ها به ذهنم مي رسه سازنده يا Constructor هست .
سازنده چيه ؟
يه تابع عضوه که حتما بايد همنام با کلاس باشه . سازنده ها هيچ وقت نمي تونن يه مقدار برگردونن . بنابراين هيچ وقت نبايد نوع داده برگشتي براشون مشخص بشه . حتي void .
فعلا اينجا من يه پرانتز باز ايجاد مي کنم و توضيحاتي در مورد توابع ميگم . پرانتز بسته رو هم ميگم تا مطالب رو از اينجا پي بگيرين .
پرانتز باز :
خب تو رياضيات که تابع ديدين ؟ تابع ++C هم تقريبا همونه . يعني يه چيزي يا يه چيزايي بهش مي ديم و اون هم يه چيزي بعد از محاسبات به ما ميده . چيزهايي که ما بهش ميديم آرگومان يا Argument ناميده ميشن . حالا تابع رو چجوري تعريف مي کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
foo : اسم تابعه .
int قبل از اسم تابع : ميگه اين تابع يه متغير از نوع int به عنوان نتيجه کار برمي گردونه .
سه متغير تعريف شده داخل پرانتز هاي بعد از نام تابع : پارامترهاي تابع رو مشخص مي کنن . يعني اين تابع براي انجام کارش سه تا آرگومان مي گيره که همش از نوع int هستن .
داخل تابع اين سه تا رو در هم ضرب کرديم و برگردونديم . با دستور return يه مقداري رو از تابع بر مي گردونيم .
شايد بپرسين آرگومان چيه ، پارامتر ( Parameter ) چيه ؟
تقريبا ميشه گفت پارامتر اون چيزيه که تو تعريف تابع ظاهر ميشه . مثل بالا . يعني a و b و c پارامترهاي تابع هستن .
حالا آرگومان .
وقتي مي خوايم تابعي رو فراخواني کنيم که يه کاري رو براي ما انجام بده ما آرگومان رو بهش مي فرستيم و اين آرگومان يا آرگومان ها تو پارامترها قرار مي گيرن و نتيجه برگردونده ميشه .
مثلا :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اينجا به تابع foo سه تا آرگومان فرستاديم که اين آرگومان ها مي رن تو تابع به جاي a و b و c قرار مي گيرن و نتيجه برمي گرده و داخل result قرار مي گيره .
فعلا پرانتز بسته .
وقتي مي خوايم يه شيئي از کلاسمون نمونه سازي يا instancing کنيم سازنده به طور اتوماتيک فراخواني ميشه و کاراشو انجام ميده . بنابراين جز اينجا ، جاي ديگه نمي تونيم به طور صريح سازنده رو فراخواني کنيم .
حالا اگه سازنده مون آرگومان داشته باشه ، هنگام تعريف شيء اين آرگومان ها رو براش مي فرستيم . ( بعد از نام شيء و داخل پرانتز )
سازنده اي که آرگومان نداشته باشه توسط کامپايلر به اسم Default Constructor شناخته ميشه . ( خيلي مهمه اين سازنده پيش فرض :46: )
فعلا کمي هم در مورد ساختار هاي کنترلي يا Control Structures :
هر برنامه ++C با استفاده از سه ساختار کنترلي نوشته ميشه .
1 - ساختار ترتيبي يا Sequence Structure : کامپايلر به ترتيب با هر دستوري که با اون مواجه مي شه اونو اجرا مي کنه .
2 - ساختار انتخابي يا Selection Structure : بسته به انتخاب کاربر يک دستور در شرايطي اجرا ميشه و در غير اين صورت يه دستور ديگه . حالت ديگه اي هم که هست اينه که يک دستور از ميان چند حالت موجود اجرا ميشه .
سه حالت داريم . حالت اول اينه که يه دستوري يا اجرا ميشه و يا نه . مثلا :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در دستور فوق اگه a برابر 22 باشه چاپ مي شه و در غير اين صورت از شرط مي پره و ميره سراغ دستورات بعدي .
حالت دوم اينه که اگه شرط برقرار باشه يه کاري و در غير اينصوري يه کار ديگه و همين طور تا آخر ... . مثلا :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اگه a برابر 22 باشه چاپ ميشه ، اگه کمتر از 22 باشه يه چيزه ديگه چاپ ميشه و اگه هيچ کدوم نباشه يه چيزه ديگه .
نکته : گذاشتن آکلاد در مواقعي که فقط يه دستور در داخل بدنه شرط داريم نياز نيست . ولي اگه بيش از يه دستور باشه بايد حتما گذاشته بشه .
حالت سوم هم دستور switch هست که يه کاري از بين چند حالت موجود اجرا ميشه .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
فهميدين چي شد ؟
a رو ميذاريم داخل يه ظرفي . اگه 1 بود one چاپ ميشه . اگه 2 بود two چاپ ميشه ، اگه 3 بود three چاپ ميشه و در غير اينصورت يه عدد ديگه .
اين break ها رو هم بذارين . اگه مثلا تو دستور اولي نذاريم ، وقتي a ، برابر 1 باشه ، دستور مربوط به اون و دستور مربوط به بقيه case ها همه اجرا ميشن . يعني هم one و هم two والي آخر ... با گذاشتن ;break از اين کار جلوگيري ميشه . حالا اگه گفتين چرا براي default نذاشتيم ؟ :20:
حالت 3 هم که حلقه هاي تکرار هستن بمونه براي بعد .
فعلا ............
sin2x=2sinxcosx
18-07-2009, 08:58
خوب حالا حالت سوم :
تو ++C ، سه نوع حلقه تکرار داريم . while ، do ... while و for
اولي ( يعني while ) :
ميگيم تا زماني که اين شرط داخل پرانتز while درست باشه ، يعني true باشه و يا هر مقدار غير صفر باشه ، اين عمليات داخل آکلاد باز و بسته بعد از پرانتز بسته شرط داخل حلقه رو انجام بده .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
راستي يه توضيحي در مورد =- بدم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا a++ با ++a چه فرقي داره ؟ وقتي ميگيم ++a يعني بعد از اينکه مقدار a تو عملياتي به کار برده شد ، بعد از اون يدونه بهش اضافه بشه . مثلا فرض کنيد a = 2 :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اينجا اول 2 چاپ ميشه بعد a ميشه 3 .
وقتي بگيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اول a برابر 3 ميشه و بعد چاپ ميشه .
در مورد - هم همين طور .
حالا دومي ( يعني do ... while ) :
در حالت قبل امکان داشت شرط حلقه همون اول غلط باشه و اصلا دستورات حلقه براي يکبار هم اجرا نشه . ولي تو do ... while همون طور که از اسم اون هم پيداست اول يه کاري يا يه کارايي انجام ميده و بعد شرط رو چک ميکنه و اگه شرط درست باشه بعد ميره دوباره همون کارو تکرار مي کنه .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا سومي که معمولا پراستفاده ترين هست . يعني حلقه for :
تقريبا ساختار کليش اين جوريه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
&& هم همون "و" هست تو رياضيات . || هم معادل "يا" هست و ! هم علامت نقيض هست . يعني ( a == 3 )! يعني a != 3 .
در اين حلقه for ، اول به متغيرها مقدار اوليه داده ميشه . يعني i = 0 و j = 0 و k = 4 . بعد شرط رو چک مي کنه و بعد ميره داخل دستورات بدنه رو اجرا مي کنه . وقتي به آکلاد بسته رسيد بر مي گرده اول هر کدوم رو يدونه ++ مي کنه و بعد دوباره شرط رو چک مي کنه و اگه درست باشه دو باره ميره سراغ دستورات .
خوب حالا توابع تا اينجا بمونن . ميريم سراغ آرايه ها و مختصري از اشاره گرها و بعد هم ديگه آخرين مفاهيم شيءگرايي .
سلام.
عالیه دوست من.
ادامه بده....خیلی عالیه...
ممنونم.
Peyman2003
18-07-2009, 13:46
توضيحاتت خوبه اما خيلي از اينور به اونور مي پري، ترتيبي تو آموزشت نداري يهو رفتي كلاس درس ميدي در حلي كه قبلش كلي مطالب بايد ميگفتي
توضيحاتت خوبه اما خيلي از اينور به اونور مي پري، ترتيبي تو آموزشت نداري يهو رفتي كلاس درس ميدي در حلي كه قبلش كلي مطالب بايد ميگفتي
برعکس خیلی هم خوب پیش میره، اگر با شی گرایی شروع کنیم خیلی به نفعمون میشه چون بعدا به هر چیزی به شکل یه آبجکت نگاه میکنی و ...(معلوماتم ته کشید:31:)
Peyman2003
18-07-2009, 15:00
برعکس خیلی هم خوب پیش میره، اگر با شی گرایی شروع کنیم خیلی به نفعمون میشه چون بعدا به هر چیزی به شکل یه آبجکت نگاه میکنی و ...(معلوماتم ته کشید)
من نميگم بد توضيح ميدن خيلي خوبه اما يهو پريدن به جايي واسه كسي كه هيچي نميدونه كمي عجيب ميشه! منم خودم يه زماني...
به نظرم پله ها رو بالا پايين رفتن
Peyman2003
18-07-2009, 15:04
من اگه خدا عمري بده از 5 شنبه به ايشون كمك ميكنم و كلاس رو كاملا توضيح ميدم اگه حالم خوش بودش آخه 5 شنبه كنكور كارشناسي دارم و فكر نمي كنم قبول بشم :41::37::9:
sin2x=2sinxcosx
18-07-2009, 17:16
سلام .
ممنون از اظهارنظرهايي که کردين .
در مورد آرايه ها و اشاره گرها به طور مختصر توضيح مي دم و يکراست ميرم سراغ شيء گرايي و مطالب باقيمونده به مرور تو اون بحث ها مطرح ميشه .
آرايه :
يه آرايه رو ، ساختمان داده اي فرض کنين که تمام اعضاي اون از يک نوع هستن . ( يا همشون int ، يا همشون char و ... )
مي خوايم يه آرايه ي 5 عضوي تعريف کنيم از نوع int
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اينجا متغير a داراي 5 خانه است که تو هر کدوم ميشه يه متغير از نوع int جاي داد . حالا چجوري به اين خونه ها دسترسي داشته باشيم :
فرض کنين آرايه مونو تعريف کرديم . مي خوايم مقاديري توي آرايه درج کنيم . اين آرايه در واقع شامل 5 متغير زير است :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
به اون اعدادي که توي دو تا علامت [] قرار مي گيره انديس يا index مي گيم . انديس آرايه از صفر شروع ميشه . به خاطر همين هميشه انديس آخرين خونه ي آرايه يکي کمتر از ظرفيت آرايه است . ( فهميدين که چي شد ؟ :46: )
دو تا مفهوم معمولا در مورد آرايه مطرح ميشه که خيلي مهمه :
1 - انديس n ام .
2 - n امين عضو .
فرض کنين اين آرايه رو به شکل زير مقدار دهي کرديم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
وقتي ميگيم انديس سوم آرايه a ، يعني عدد 6 .
وقتي ميگيم سومين عضو يعني عدد 5 .
ديدين چقدر مهم بود ؟ :31: .
يه چيز ديگه .
a يک آرايه است . يعني حاوي آدرس اولين خونش . چون اين آرايه از نوع int هست و int هم چهار خونه حافظه مي گيره پس آدرس خونه بعدي که انديس 1 باشه ميشه آدرس خونه اول + 4 . :46:
اين نکته خيلي جالبه ها . به غير از آرايه ها هيچ جا نميشه به صراحت گفت که آدرس دو خونه تو حافظه پشت سر هم باشه .
مقدار دهي اوليه به آرايه ها:
اگه تو تعريف آرايه که مقدار دهي کردين هيچ ، اگه نکردين تو يه جاي ديگه بايد دونه به دونه مقدار دهي کنين . مثل اون بالا کاري که من کردم .
حالا فرض کنيم تو تعريف آرايه ميخوايم مقداردهي کنيم . چندين حالت داريم که نمي دونم چند حالته . حالا بگم بعد مي شمرم . :46:
اول اينکه اگه بخوايم تو تعريف آرايه مقدار دهي کنيم بايد ليست مقادير داخل آکلاد باز و بسته باشه .
دستور زير رو در نظر بگيرين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مي بينين که ما يه آرايه 5 عضوي تعريف کرديم و براي چهار تا عضو مقدار اوليه مشخص کرديم . عضو آخر که مقدار نداره ، مقدار صفر مي گيره .
حالا يه سوال :
اگه بخوايم به همه صفر بديم ، چيکار کنيم راحت تره ؟ :46:
.
.
.
آفرين . درسته . دستور زير رو مي نويسيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
به عضو اول صراحتا مقدار صفر داديم ، بقيه هم که مقدار نگرفتن ، به طور پيش فرض صفر مي گيرن .
يه حالت هم اينه که اگه آرايه 5 عضوي تعريف کرديم ، 5 تا عدد تو ليست بنويسيم . تو اين هم که حرفي نيست . به طور صريح به همه مقدار داده ميشه .
حالت سوم اينه که ليست مقدار اوليه بيشتر از طول آرايه ( تعداد اعضاي آرايه ) باشه . در اين حالت Compile Error.
يه حالت هم اينه که :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تو اين جا مي بينين که تعداد اعضا مشخص نشده . همون طور که احتمالا حدس زدين ، تعداد اعضا ميشه 7 . چون تو ليست مقدار اوليه ، 7 عدد مشخص شده . بنابراين از [ a [ 0 داريم تا [ a [ 6 .
فکر کنم شد 4 حالت . :46:
حالا آرايه هاي کاراکتري :
همون طور که قبلا اشاره شد نوع داده char فقط مي تونه يک کاراکتر يا همون حرف تو خودش داشته باشه . حالا اگه بخوايم چند کاراکتر يا همون به قول ++C ، رشته داشته باشيم مي تونيم آرايه اي از کاراکتر ها رو تعريف کنيم .
تعريفش که فرقي نمي کنه . فقط نکاتي در مورد مقدار دهي اوليه مي گم .
به دو روش مي تونيم به آرايه هاي کاراکتري مقدار اوليه بديم .
روش اول :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
الان کامپايلر اين دستورو به شکل زير پردازش کرده :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
هميشه آخرين عضو يک آرايه کاراکتري 0\ در نظر گرفته ميشه .
متوجه هستيد که در اينجا تعداد اعضا مشخص نبود. بنابراين تعداد اعضا برابر 11 ميشه .
يه حالت مقدار دهي هم به شکل زير است :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يعني کاراکترها رو دونه به دونه بهش ميديم و آخر سر هم حتما بايد کاراکتر 0\ رو ما مشخص کنيم . ولي در حالت اول نياز نبود . اگه بخوايم تعداد اعضاي آرايه رو خودمون مشخص کنيم ، حتما بايد يه جاي اضافي هم براي 0\ در نظر بگيريم . مثلا اگه مي خوايم sin رو داشته باشيم بايد به جاي 3 خانه ، 4 خانه در نظر بگيريم . در غير اين صورت Compile Error
نکته مهم : اگه نمي خوايم تو تعريف آرايه مقداردهي رو انجام بديم ، حتما بايد تعداد اعضا ذکر بشه . مثلا دستور زير = Compile Error .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
آرايه هاي دو بعدي :
آرايه هاي اخير که بحث شد همه يک بعدي بودن . مفاهيم آرايه هاي دوبعدي هم تقريبا همينه .
براي تعريف آرايه دوبعدي 3 در 4 :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين يعني 4 سطر و 5 ستون . ( چون انديس گذاري آرايه ها از صفر شروع ميشه . )
دستور زير رو در نظر داشته باشين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مقدار دهي فوق به صورت زير پردازش ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
البته آرايه هاي بيش از دو بعدي هم داريم . مفاهيم همينا هستن . معمولا از آرايه هاي سه بعدي به بعد به ندرت استفاده ميشه .
اين هم از آرايه ها ................... :46:
sherlockholmz
19-07-2009, 11:17
جناب آقاي (ويا به احتمال 1% خانم:46:) sin2x=2sinxcosx :
با سلام
با تشكر مجدد از جنابعالي، مطمئنا" بسياري از اين مساعي مستفيض مي گردند كه بنده نيز در اين حلقه ام.لذا مستدعيست مراتب باي نحو كان پيگيري و سعايت بدگويان مانع از ادامه تلمذ نگردد .صحت مسير تائيد و روش خلاقانه اتان دريافت نهايه را ميسور مي نمايد.زياده جسارت است.حق يارتان
دوست كوچكتر شما
CppBuilder2006
20-07-2009, 00:36
فقط تجربه خودمو میگم. اگه نویسنده اول یه فهرست از مطالبی که قرار گفته بشه درست کنه، آخر کار مرتب کردن مطالب خیلی راحت تره. بی فهرست برای هر نظم دادنی باید کلی تغییر بده. میشه حتتا پستای ناقصی نوشت و بعدا کاملشون کرد!
sin2x=2sinxcosx
20-07-2009, 12:36
سلام . باز هم ممنون از دوستان عزيز بابت اظهارنظرهايي که فرمودن .
در مورد اينور و اونور پريدن : باشه ديگه تکرار نمي شه . ( همون طوري که ديدين تو بحث آرايه ها ديگه اين کارو نکردم . )
در مورد فهرست هم : چشم براي از اين به بعد فهرست مي ذارم .
ولي باز هم جمله قبليمو تکرار مي کنم :
"خواهشا از هيچ گونه اشتباه علمي و املايي چشم پوشي نکنيد و حتما تذکر دهيد ."
فهرست مطالبي که بعدا بحث ميشه :
1- نابود کننده ها يا Destructor ها
2- اشياء Const و توابع Const
3- کلاس ها و توابع Friend و مفهوم دوستي در کلاس ها
4- اشاره گر this
5- عملگر هاي new و delete
6- اعضاي static کلاس و مفهوم static بودن
7- بحثي کامل در مورد Operator Overloading يا همون سربارگذاري عملگر ها
8- ارث بري و مفاهيم مربوط به آن
9- مبحث Polymorphism و توابع Virtual
10- بحث در مورد توابع بازگشتي
11- اشاره گرها
12- کار با فايل ها
13- مباحثي در مورد ساختمان داده ها ( صف و پشته و ليست پيوندي و ... )
14- آشنايي با وپژگي هاي کلاس string و نحوه استفاده از آن
15- حل مسائل گوناگون مطرح در زبان ++C
ان شاءالله که عمري باقي باشه و بتوان به تمامي اين موارد رسيد .
موفق باشيد .............
sin2x=2sinxcosx
21-07-2009, 09:24
سلام. اگه اجازه بدين اشاره گرها رو شروع کنيم .
چون بعدا نياز ميشه .
اشاره گرها يه نوع متغير هستن . اما به جاي يک مقدار ، يک آدرس متغير رو تو خودشون نگه مي دارن .
در زير من يک متغير اشاره گر که به يک مقدار صحيح ( يعني int ) اشاره مي کند ، معرفي مي کنم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اگه بخوايم بيش از يک متغير اشاره گر رو تو يک خط معرفي کنيم بايد قبل از هر کدوم يه star ( * ) بذاريم . عملگر * تو بالا نشون ميده که متغير aPtr يک اشاره گر به int هست .
به غير از آدرس يک متغير ، عدد صفر تنها مقداري است که مي تواند در يک متغير اشاره گر قرار گيرد .
با عملگر & ميشه به آدرس يه متغير دسترسي داشت . مثلا در زير ما با آدرس يک متغير به اشاره گر بالايي مون مقدار ميديم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
آدرس يه متغير يه همچين عدديه : 0015F670 . لازم به ذکره که خود متغيرهاي اشاره گر داراي آدرس هستن .
همون طوري که ديدين ، آدرس متغير a رو تو يه اشاره گر به int قرار داديم . حالا هر تغييري که تو مقدار اين اشاره گر ميشه ، تو a هم اعمال ميشه .
فرش کنين که a = 3 باشه . ما اگه بخوايم aPtr رو چاپ کنيم يه آدرس ( آدرس متغير a ) چاپ ميشه . اگه بخوايم مقدار اون محلي که اين اشاره گر به اون جا اشاره مي کنه چاپ بشه از عملگر * به شکل زير استفاده مي کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
الان عدد 3 چاپ ميشه .
يه مطلب مهم تو آرايه ها و اشاره گرها که يه کمي دقت مي خواد :
قبلا تو آرايه ها گفتيم که آدرس خونه هاي يک آرايه پشت سر هم هستن . فرض کنين آرايه b رو با 4 عضو داريم . يعني :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه اشاره گر هم داريم که آدرس خونه اول اين آرايه رو داره . يعني :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
همون طور که مي دونين اسم آرايه معادل آدرس خونه اول آرايه است . يعني دستور زير با دستور بالايي فرقي نداره :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا ++bPtr باعث ميشه که bPtr به جاي عضو اول به عضو دوم اشاره کنه . دستور bPtr +=2 باعث ميشه که اشاره گر bPtr به عضو سوم آرايه اشاره کنه .
يادتونه گفتم ؟
"به غير از آرايه ها هيچ جا نميشه به صراحت گفت که آدرس دو خونه تو حافظه پشت سر هم باشه ."
اين جا هم يه چيزي ميگم :
استفاده از اين گونه محاسبات روي اشاره گري که به يک آرايه اشاره نمي کند خطاي منطقيه .
اين دو جمله کاملا به هم مربوطن .
sin2x=2sinxcosx
21-07-2009, 20:21
خوب حالا تقريبا ميشه گفت به طور کامل وارد بحث کلاس ها و شيء گرايي شديم . از اين به بعد هر چقدر بگين مطلب رو کشش مي ديم . هر سوالي در اين رابطه هست بپرسين . يا من و يا اگر من هم بلد نباشم اين جا اساتيد حضور دارن که مي تونن راهنمايي کنن .
Destructor يا نابود کننده :
همون طوري که گفتيم سازنده يا Constructor تابع عضو خاصي از يه کلاسه که زماني فراخواني ميشه که يک شيء از اون کلاس ايجاد ميشه . جاي ديگه نمي تونيم به طور صريح اين تابع رو فراخواني کنيم . در مقابل Constructor ، نابود کننده يا Destructor قرار داره . Destructor هم به طور اتوماتيک احضار ميشه . خوب کي ؟
همون طوري که احتمالا حدس زدين ، زماني که يک شيء نابود ميشه .
خب شيء نابود ميشه يعني چي ؟
فرض کنين شيء رو داخل يه تابع تعريف کرديم . تابع با آکلاد باز شروع ميشه و با آکلاد بسته تموم ميشه . تموم ميشه يعني کار تابع به پايان مي رسه و اجرا خاتمه مي يابه . پس بنابراين وقتي اجراي برنامه به آکلاد بسته مي رسه يعني Scope اي که شيء تو اون تعريف شده ترک ميشه و اين به معناي نابودي شيء هست . وقتي برنامه رو Trace کنين ( يعني خط به خط اجرا کنين و تغييرات رو هر لحظه ببينين ) متوجه ميشين که وقتي اجراي برنامه به آکلاد بسته مي رسه ، Destructor احضار ميشه .
نابود کننده هم مثل سازنده هيچ چيزي برنمي گردونه . بنابراين در مورد Destructor هم از کلمه void به عنوان نوع داده برگشتي استفاده نمي کنيم . حالا نابود کننده بر خلاف سازنده هيچ آرگوماني هم نمي تونه بگيره . بنابراين ليست پارامترهاي نابود کننده هميشه خاليه . حالا چجوري به کامپايلر بفهمونيم که کدوم تابع عضو ما Destructor هست ؟
مثل سازنده بايد دقيقا اسم کلاس باشه ، فقط قبلش يه علامت tilde ( ~ ) هم مي ذاريم .
خوب من اون بالا يه جمله اي گفتم : "چجوري به کامپايلر بفهمونيم که کدوم تابع عضو ما Destructor هست ؟"
چه اصراريه به کامپايلر اينو بفهونيم ؟
بله درسته ...
چون کامپايلر سازنده و نابودکننده رو احضار ميکنه نه برنامه نويس . بنابراين بايد براش بشناسونيم .
يه فرق ديگه اي که سازنده با نابودکننده داره اينه که تو هر کلاس ميشه چند تا سازنده داشت ولي نابود کننده يدونه است . :46:
sin2x=2sinxcosx
22-07-2009, 14:50
در مورد اشياء و توابع const :
اگه بخوايم يه شيئي رو به صورت const تعريف کنيم ، بايد قبل از نام کلاس کلمه کليدي const رو بذاريم . مثلا مي خوايم از کلاس Polynomial يه شيء const به نام poly بگيريم . مي نويسيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه نکته :
اگه بخواين از يکي از انواع داده اي اصلي ++C مثل int متغير const تعريف کنين ، بايد تو همون خط ، يعني تعريف متغير مقدار دهي اوليه کنين . در غير اين صورت Compile Error دريافت مي کنين با اين مضمون :
const object must be initialized if not extern
ولي براي دستور بالايي ما که يک نوع داده اصلي نيست ، بلکه يه کلاسه ، ايراد نمي گيره و اجازه مي ده برنامه اجرا بشه . ولي با اين همه يه warning ميده . اون هم در يه شرط . چه شرطي ؟ الان ميگم :
گفتيم که Constructor يه کلاس هنگامي فراخواني ميشه که شيئي از اون کلاس ايجاد بشه . خوب حالا ما مي تونيم هرکاري که دلمون مي خواد تو اون constructor انجام بديم . مثلا ما اين جا مي تونيم به داده هاي عضو کلاس مقدار اوليه بديم تا هنگامي که شيئي ايجاد مي شه همه داده هاي عضو مقدار اوليه داشته باشن . در اين صورت وقتي شيء به صورت const تعريف ميشه ، ديگه warning هم نميده . چون ديگه به محض تعريف شيء ، داده ها مقدار اوليه شونو توسط سازنده گرفتن . وقتي Constructor مون خالي باشه ، هنگام تعريف يک شيء از اون کلاس به صورت const ، پيغام هشدار يا warning دريافت مي کنيم .
براي تعريف يه تابع عضو به صورت const هم بايد کلمه const رو بعد از پرانتز بسته ليست پارامترها قرار بديم .
چند نکته در مورد توابع عضو const و اشياء const
1- اشياء const نمي تونن هيچ تابع عضوي رو احضار کنن ، مگر اينکه خود تابع عضو هم const باشه .
2- توابع عضو اعلان شده به صورت const نمي تونن داده هاي عضو يک شيء رو تغيير بدن .
3- خود تابع عضوي که const هست نمي تونه تابع عضو غير const همون کلاس رو احضار کنه .
4- سازنده ها و نابودکننده کلاس ها همواره شيء رو تغيير مي دن . بنابراين شيء شما چه const باشه و چه غير const ، اونا مجاز هستن عمليات خود رو روي شيء انجام بدن .
5- نمي تونيم سازنده ها و نابود کننده يک کلاس رو به صورت const تعريف کنيم .
6- يه شيء غير const مي تونه تابع عضو const همون کلاس رو احضار کنه .
فکر کنم ديگه تموم شد . اگه نکته اي موند بگين . :20:
sin2x=2sinxcosx
26-07-2009, 15:47
سلام . چند روزي بود نبودم ... ببخشيد از وقفه اي که پيش اومد . سعي مي کنم تا يه هفته تموم کنم و برم . چون تا چند هفته بعد ديگه نمي تونم بيام . نه اينترنت و نه P30World . اگر هم تموم نشد يا دوستان ادامه ميدن و يا بعد از يه ماه خودم .
حالا .................
کلاس ها و توابع friend :
قبلا گفتيم که خارج از کلاس نميشه به داده ها يا توابع عضو يه کلاس که به صورت private تعريف شدن به طور مستقيم دسترسي داشت .
حالا اگه يه کلاس يا يه تابعي به صورت friend يه کلاس تعريف بشه ، اين کار شدنيه .
مي خوايم يه تابعي رو براي کلاس Chess به صورت friend يا دوست تعريف کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مي خوايم يه کلاس ( کلاس A ) رو براي کلاس Chess به صورت friend تعريف کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
نکته : ديدين که کلاس Chess تعيين کرد که کدوم تابع يا کلاس دوست اونه . چون قراره از داده هاي private کلاس Chess استفاده بشه . والا نميشه يه کلاس تعريف کنيم بگيم اين کلاس ما ، دوست کلاس شماست و راحت از داده هاي اون استفاده کنيم . در اين صورت کلا مباني و مفهوم برنامه نويسي شيء گرا زير سوال ميره . :18:
sin2x=2sinxcosx
28-07-2009, 00:30
اشاره گر this و کاربرد اون :
گفتيم وقتي يه کلاس رو تعريف مي کنيم ، توابع عضو اين کلاس مي تونن به طور مستقيم به داده هاي عضو کلاس دسترسي داشته باشن . يعني فرض کنين ما متغير x رو به عنوان داده عضو براي کلاس A تعريف کرديم و مي خوايم تو يه تابع عضو مقدار اون رو تغيير بديم . سه راه داريم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در حالت اول به طور ضمني از اشاره گر this براي دسترسي به داده عضو کلاس استفاده شده . در دومي و سومي هم به طور صريح . در اينجا تقريبا فرض کنين this يه شيء از کلاسه . چون this يه اشاره گر هست ، بنابراين براي دسترسي به داده هاي عضو کلاس مربوطه بايد به جاي . از <- استفاده کنيم . وقتي از * استفاده مي کنيم ، بايد از . براي دسترسي استفاده کنيم .
استفاده از اين اشاره گر در مبحث سربارگذاري عملگر ها مفيده .
در مورد تخصيص پوياي حافظه :
شکل کلي دستور اين طوريه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين براي گرفتن بود . براي پاک کردن هم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مثال :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مثال براي تخصيص حافظه براي يک آرايه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تخصيص حافظه به صورت پويا يه کاربردش اينه که مثلا شما از کاربر بخواين يه عددي رو وارد کنه و شما از اون عدد به عنوان طول يک آرايه استفاده کنين . ( در حالت عادي شما نمي تونين از متغيرهاي غير ثابت براي طول آرايه استفاده کنين . )
نکته : اگه براي يه متغير به صورت پويا حافظه گرفته باشين و اونو پاک نکنين ( توسط دستور delete ) ، اين حافظه به صورت garbage يا آشغال در حافظه مي مونه و بلااستفاده باقي مي مونه .
البته زبان هاي پيشرفته ديگه مثل #C يه قابليتي به نام garbage collector دارن که مي تونن اين کارو به طور اتوماتيک انجام بدن ولي ++C نداره . ( البته تو نسخه Native ) .
در مورد اعضاي static يک کلاس :
فرض کنين يه کلاس ، يه متغير به اسم i داره . توسط constructor بهش مقدار 0 مي ديم . بنابراين با هر شيئي که از اين کلاس ايجاد ميشه ، يه کپي از متغير i براش ايجاد ميشه و بهش مقدار 0 داده ميشه . اين ويژگي يک عضو غير static کلاس هست .
ولي يک عضو static براي کل کلاس هست . 100 تا شيء هم از يه کلاس ايجاد بشه براي همشون به عضو static داريم . فقط يکبار مقدار اوليه به متغير static داده ميشه . اگه شيئي از کلاس نداشته باشيم باز هم ميشه به مقدار يه متغير static دسترسي داشت . ( با تايپ نام کلاس و دو تا دونقطه و نام متغير static ) .
فعلا تا اينجا بمونه ...
sin2x=2sinxcosx
28-07-2009, 18:42
قبل از اينکه وارد مبحث Operator Overloading بشم ، يه مثال از کتاب ديتل در مورد کلاس ها ميارم ، خط به خط توضيح ميدم و آخر سر يه بار Trace مي کنم تا مطالب خوب جا بيفتن .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
خوب ...
اين قطعه کد تعريف يک کلاس رو نشون ميده . اين قطعه کد يه فايل با پسوند h. هست نه cpp. ! برنامه هاي سي پلاس پلاس تو فايل هايي با پسوند cpp. ذخيره ميشن . ولي اين يه کد قابل اجرا نيست و فقط شامل پيش نمونه توابع عضو کلاس هست . گفتيم که اگه بخوايم از اشياء cin يا cout تو برنامه مون استفاده کنيم بايد فايل iostream رو توسط دستور پيش پردازنده include تو برنامه مون بگنجانيم . اين فايل رو داخل <> قرار مي داديم . اين نشون ميده که اين فايل داخل پوشه include کامپايلر قرار داره . اين قطعه کد بالايي ما هم يه چيزي مثل iostream هست . يعني براي اينکه از اين کلاس يه شيء بگيريم ، بايد اين فايل رو include کنيم . ولي اين فايل داخل پوشه include کامپايلر نيست . بنابراين اين رو داخل "" قرار مي ديم . در اين صورت هنگام پيوند دادن برنامه ، وقتي مي خواد تابع main اجرا بشه اين فايل رو در کنار فايلي که تابع main تو اون قرار داره مي گرده . همون طوري که مي بينين اسم کلاس ما ، Time هست . بعد آکلاد باز مياد و کلمه public رو مي بينين . يعني توابع زير اون حالت عمومي دارن و همه جا قابل مشاهده و فراخواني هستن . يه سازنده ، يه تابع به اسم setTime ، که سه پارامتر int مي گيره و چيزي بر نمي گردونه . تابع هاي printUniversal و printStandard که نه پارامتر دارن و نه چيزي بر مي گردونن . بعد سه تا متغير int از نوع private ، داده هاي عضو کلاس رو تشکيل مي دن .
همون طوري که مي بينين اين فايل ما حاوي پياده سازي توابع نيستن . بنابراين نياز به يه فايل ديگه داريم تا تو اون هم پياده سازي توابع رو داسته باشيم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين همون فايل پياده سازي هاي توابع هست . تو خط اول فايل iostream رو include کرديم . در خط بعد تعريف شيء cout رو انجام داديم . بعد براي استفاده از اشياء setw و setfill ، فايل iomanip رو include کرديم . بعد خود فايل h. کلاسمون رو include کرديم . يه نکته اي که هست اينه که براي تعريف توابع عضو کلاس ، قبل از اسم توابع ، اسم کلاس رو به همراه دو تا دونقطه مياريم . پياده سازي هم مثل پياده سازي معمولي تو برنامه نويسي ساخت يافته است .
يه فايل ديگه حاوي تابع main لازم داريم تا بتونيم از اين کلاس استفاده کنيم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
داخل تابع main ، يه شيء به اسم t از کلاس Time نمونه سازي کرديم . با اين دستور ، کامپايلر ميره سراغ Constructor کلاس مربوطه ، تا شيء رو بسازه . :46:
مي بينين که تو سازنده يا Constructor ، ما به داده هاي عضو کلاس ، مقدار صفر داديم . بنابراين داده هاي عضو شيء t هم مقادير صفر رو گيرن . چهار خط بعدي با فراخواني توابع چاپ داده هاي عضو کلاس ، اين مطلب رو تاييد مي کنن . ما يه تابع عضو ديگه به اسم setTime تو کلاسمون داشتيم که اجازه ميداد سه تا آرگومان بهش بفرستيم تا اون مقادير رو داخل داده هاي عضو قرار بده . بنابراين تو خط بعدي ما از اين تابع استفاده مي کنيم و مقادير خودمون رو بهش پاس ميديم و در تاييد اين مطلب دوباره توابع چاپ رو قراخواني مي کنيم .
خروجي برنامه بالاخره اين ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
سلام.
خیلی ممنون از این تاپیک مفید.
3 تا سوال:
1- چرا تو Main اون Time.h رو include کردید به جای Time.cpp ؟
2- هیچ وقت دلیل استفاده از این header ها رو تو C نفهمیدم! چرا مثل #C در جا تعریف و پیاده سازی نمی کنند؟
بعد اینی که گذاشتید خیلی ناجوره!
یعنی هرکی این Header رو داشته باشه، خیلی راحت فقط Class::Method رو می نویسه و تعریفش می کنه؟
آخه 1 کم با مفهوم کپسوله سازی و کلاً شیء گرایی نمی خونه!
3- چرا شما New نمی کنید این کلاس ها رو؟
آخه اونجوری که مثلاً می نویسید Time t که Constructor اجرا نمیشه! (یا حداقل تو #C اینجوریه!)
اینجوری فقط میشه یه اعضای Static دسترسی داشت! (یا حداقل تو #C اینجوریه!)
--
اون پست 23 هم فکر می کنم 1 کم عجله ای نوشتید و یک کم نا مفهوم شده!
در کل من Fan این تاپیک شدم!
از کنارش جم نخواهم خورد.
شما هم ادامه بدید.
با آرزوی موفقیت.
sin2x=2sinxcosx
28-07-2009, 20:44
سلام دوست عزيز .
1- هميشه تو ++C فايل هدر رو include مي کنيم . چون هر سه فايل Time.h و Time.cpp و main.cpp در يک فولدر قرار دارن ، با include کردن Time.h ، کامپايلر مي تونه فايل cpp مربوط به اون هدر رو پيدا کنه و Link کنه .
2- اتفاقا اين کلاس رو به دو فايل h. و cpp. تبديل مي کنيم تا مفهوم شيء گرايي حفظ بشه . به کاربري که قصد استفاده از اين کلاس ما رو داره فقط فايل هدر داده ميشه که فقط اينو بدونه که اين کلاس ما چه توابعي دارن و چه آرگومان هايي مي گيرن . با ارائه توضيحات در فايل هدر توسط برنامه نويس کلاس ، ميشه بهتر کاربر برنامه نويس تابع main رو در جهت استفاده از کلاس راهنمايي کرد . فايل کامپايل شده فايل cpp کلاس هم به مشتري يا همون استفاده کننده از کلاس داده ميشه که بتونه به فايل h. پيوند بزنه . Source فايل cpp نبايد در دسترس مشتري قرار بگيره و اين همون مفهوم کپسوله سازي و مهندسي نرم افزار و تکنولوژي شيء گراييه که مشتري نبايد از چگونگي پياده سازي توابع اطلاع داشته باشه . فقط کافيه بدونه که چه توابعي وجود دارن و اين توابع چيکار مي کنن . ديگه لازم نيست بدونه که چه الگوريتمي براي انجام اين کار پياده سازي شده .
در مورد اين هم که هر کس فايل هدر رو داشته باشه مي تونه فايل cpp رو از روي اون بنويسه ، بايد بگم که خوب بنويسه . چه اشکالي داره . مهم اينه که به پياده سازي مدنظر ما لطمه وارد نشه .
3- تو ++C فقط کافيه بنويسيم Time t . در اين صورت Constructor ( البته سازنده پيش فرض يا Default Constructor ) اجرا ميشه . حالا فرض کنين Constructor ما يه پارامتر داره از نوع int . بنابراين هنگام تعريف شيء ، مثلا مي نويسيم ( Time t ( 3 . در اين حالت عدد 3 رو به عنوان آرگومان به Constructor مي فرستيم .
در مورد پست 23 هم حق کاملا با شماست . ولي قصد من اين بود که بعدا توسط مثال هايي به اين مطالب پرداخته بشه . فقط خواستم يه پيش نمونه ذهني در اين مورد ايجاد بشه .
موفق باشيد ... :11:
خیلی ممنون.
نمی خوام تاپیکتون رو الکی شلوغ کنم.
بعداً می تونید به همکار ها بگید که پستم رو حذف کنند.
---
با توجه به این توضیحی که در مورد Header دادید، یاد Interface افتادم!
شبیهش ه دیگه!
+
نفرمودید، میشه همزمان تعریف و پیاده سازی کرد یا نه!
در مورد Instancing ، مگر نباید بنویسیم ;() Time t = new Time ؟
یعنی این الان Error میده؟
باز هم ممنون از توضیحتون.
sin2x=2sinxcosx
29-07-2009, 10:14
خیلی ممنون.
نمی خوام تاپیکتون رو الکی شلوغ کنم.
بعداً می تونید به همکار ها بگید که پستم رو حذف کنند.
---
با توجه به این توضیحی که در مورد Header دادید، یاد Interface افتادم!
شبیهش ه دیگه!
+
نفرمودید، میشه همزمان تعریف و پیاده سازی کرد یا نه!
در مورد Instancing ، مگر نباید بنویسیم ;() Time t = new Time ؟
یعنی این الان Error میده؟
باز هم ممنون از توضیحتون.
اختيار داريد . اين تاپيک براي آموزش هست چرا بايد سوال ها حذف شوند ؟ ( البته آموزش که نه ، شما استاد ما هستيد )
بله به اين هدرفايل مي گيم Interface و به پياده سازيش ميگيم Implementation . شبيه نيست دقيقا همونه .
اگه منظورتون از همزمان تعريف و پياده سازي کردن اينه که فايل h. و cpp. يدونه باشن بايد بگم بله ميشه . قبلا هم گفتم . ما به اين دو فايل تبديل مي کنيم تا شيوه به کار گرفته شده در پياده سازي توابع عضو به صورت پنهان باقي بمانند .
در مورد اون شکل Instancing هم که شما فرموديد به جاي اون بايد از دستور زير استفاده کنيم . يعني t از نوع اشاره گر به Time گرفته شود . در اين صورت ( شکل تعريف شما ) تخصيص حافظه براي t به صورت دايناميک و در هنگام اجراي برنامه گرفته مي شود که مي توانيم هر زمان که خواستيم با دستور delete آن را به حافظه بازگردانيم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
sin2x=2sinxcosx
30-07-2009, 20:21
يه مثال هم در مورد ترتيب فراخواني سازنده و نابود کننده توسط کامپايلر ميگم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين يه کلاسه که فقط يه Constructor داره و يه Destructor . دو تا هم داده عضو داره که يکيش از نوع int و دومي از نوع string که خود string هم يه کلاسه از کتابخانه استاندارد ++C .
الان اگه يه نکته بگم باز دوستان ميگن اينور و اونور نپر .
ولي ميگم . :46:
وقتي از شيء يه کلاسه ديگه تو کلاس خودمون استفاده مي کنيم ميگيم از خاصيت Composition يا ترکيب استفاده کرديم . که ميگيم CreateAndDestroy يه string داره . بعدا تو بحث ارث بري اين مفهوم رو بهتر مي فهمين . تو ارث بري هم ميگيم فلان يه فلان است .
تو اين جا message يه شيء از کلاس string هست که پياده سازي کلاس string تو کتابخانه استاندارد هستش و شما کافيه فقط اونو include کنين .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين هم پياده سازي اين کلاس .
يه نکته اي بگم .
لازم نيست تو نابود کننده اين کارايي که تو بالا انجام گرفته انجام بديم . چون اين يه مثاله و مي خوايم ترتيب فراخواني سازنده و نابود کننده معلوم بشه ، اين پيغام ها رو چاپ کرديم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين هم تابع main بود .
تو اينجا با مفهوم static بودن هم آشنا ميشين .
يه تابع تعريف کرديم به اسم create که نه چيزي مي گيره و نه چيزي برميگردونه .
بعد يه شيء سراسري يا Global از کلاسمون تعريف کرديم . چون سازنده مون دو تا پارامتر داره پس موقع تعريف شيء هم دو آرگومان براش مي فرستيم . اوليش از نوع int و دوميش از نوع string . ( رشته ها داخل " " قرار مي گيرن . ) چون سازنده فراخواني ميشه ، پس دستورات موجود تو اون اجرا ميشه . پس با اجراي برنامه ، ابتدا پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تابع main شروع ميشه . پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
باز يه شيء ايجاد مي کنيم و سازنده فراخواني ميشه و يه پيغام چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بعد يه شيء static تعريف مي کنيم و سازنده فراخواني ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا تابع create رو فراخواني مي کنيم . اجرا از تابع main منتقل ميشه به تابع create .
با اجراي تابع create پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
با تعريف يک شيء داخل اين تابع سازنده فراخواني ميشه و در نتيجه پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه شيء static ديگه تعريف مي کنيم و باز پيغام چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
دوباره يه شيء ديگه و فراخواني سازنده و چاپ پيغام :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بعد پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا يکي از نکات مهم اينجاست . مي بينين که به پايان تابع create رسيديم . پس با تموم شدن اجراي اين تابع ، اشيايي که تو اون تعريف شده بودن بايد نابود بشن و اين به معناي فراخواني نابود کننده است . پس براي دو شيء 7 و 5 ، نابودکننده احضار ميشه . چرا براي 6 نه ؟ چون اون يه static بود . :46:
پيغام هاي زير چاپ ميشن :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اجراي برنامه برميگرده به تابع main .
دستور زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه شيء ديگه تعريف مي کنيم و سازنده فراخواني ميشه و پيغام زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بعد دستور زير چاپ ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا مهمترين نکته که غرض از اين مثال هم ذکر اين نکته بود .
الان کار تابع main هم تموم شد و نوبت مي رسه به نابود شدن شيء ها يکي پس از ديگري . چه static و چه غير static . حالا کدوم يکي پس از کدوم يکي ؟ اين مهمه ! :46:
چون شيء 4 آخرين شيئي بود که ايجاد شده بود پس اول اون نابود ميشه . چاپ پيغام زير هم اين مطلب رو تاييد مي کنه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بعد شيء 2 نابود مي شه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا اول اون شيء static که تو تابع create بود نابود ميشه و بعد static موجود تو تابع main :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
آخر سر هم اون شيء Global نابود ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بنابراين خروجي کامل برنامه اين ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
sin2x=2sinxcosx
31-07-2009, 10:14
سلام دوستان عزيز .
لطفا يه نظري تا اينجاي مطالب بدين تا من ادامه بدم . چون ديدگاهي که من نسبت به مطالب گفته شده دارم با ديدگاه يه فرد غير از خودم کاملا فرق مي کنه . من الان نمي دونم که از روي مطالب دارم مي پرم ؟ خيلي خلاصه مي گم ؟ خيلي کشش مي دم ؟ ... ؟
اگه لازم باشه باز هم فعلا مثال بيارم . چون مطالب بقيه به طور جدي مربوط به تکنولوژي شيءگرايي ميشه و بحث کاملا جدي تره . مخصوصا مبحث ارث بري و polymorphism .
ديگه اصلا تصميم ندارم سراغ ساخت يافته برم . متغير رو چجوري معرفي مي کنن . چجوري ورودي مي گيرن . با نوع داده double چيکار مي کنن . چه رنجي رو ساپورت مي کنه . اولويت Operator ها به چه صورته و ... .
ara.look
31-07-2009, 11:36
خوبه ادامه بده....
ممنون.
بد نیست.
هر چند از آخرین درسی که دادی، خوشم نیومد!!!
آخه خیلی کشش دادی، وسط کار یادم رفت که مطلب چی بوده! :دی
ولی ادامه بده.
+
موفق باشی.
sin2x=2sinxcosx
31-07-2009, 16:48
بد نیست.
هر چند از آخرین درسی که دادی، خوشم نیومد!!!
آخه خیلی کشش دادی، وسط کار یادم رفت که مطلب چی بوده! :دی
ولی ادامه بده.
+
موفق باشی.
سلام دوست عزيز . جالبه ! :20: راجع به پست 23 گفتين خيلي خلاصه اس . الان هم ميگين خيلي کش ميدم .
ara.look
31-07-2009, 21:10
+++++++++++++++
sin2x=2sinxcosx
31-07-2009, 22:38
من یه سوال داشتم وقتی که یه یونیت رو ایجاد میکنیم 2 تا فایل .cpp و .h ایجاد میکنه.
میخواسم بدونم که هر کدوم به چه دردی میخوره و چرا؟
لطفا کامل باشه...
ممنون
ببخشيد Unit چيه ؟
ara.look
31-07-2009, 22:43
حل شد........
CppBuilder2006
01-08-2009, 09:18
به یه فایل cpp. همراه با همۀ فایلهایی که توش include# شده میگن یه unit. تعداد unitها در یه project برابر با تعداد فایل های cpp.یه.
----------------
آموزش خوبه! البته به نظرم مخاطب یه چیزایی باید از قبل بدونه. مثال هم کم داره!
ادامه بده! من که منتظر inheritance هستم :20:
سلام به همه
من تازه كارم و دوست دارم C++ رو از پايه ياد بگيرم لطفا راهنمايي كنيد
sin2x=2sinxcosx
01-08-2009, 10:10
بابا همون .h و یا .cpp
آخه شما اول پرسيدين اگه يه يونيت ايجاد کنيم دو تا فايل h. و cpp. ايجاد مي کنه .
حالا من در مورد اين دو تا فايل در پست هاي 24 و 26 توضيح داده ام . مي تونين به اونا مراجعه کنين . h. معمولا حاوي prototype هاي توابع عضو کلاسمون هستن به اضافه تعريف کلاس و cpp. هم حاوي پياده سازي يا implementation توابع .
sin2x=2sinxcosx
01-08-2009, 12:16
سلام به همه
من تازه كارم و دوست دارم C++ رو از پايه ياد بگيرم لطفا راهنمايي كنيد
تازه کار تو ++C يا تازه کار تو برنامه نويسي يا نه تازه کار تو کامپيوتر ؟ :46:
ara.look
01-08-2009, 13:51
حل شد........
sin2x=2sinxcosx
01-08-2009, 14:08
پس در این صورت شما جایی رو که نفهمیدین بگین تا من توضیح بدم . چون اگه از من بخواین که باز در مورد h. و cpp. توضیح بدم همون مطالب قبلی رو تکرار می کنم . چرا نفهمیدین ؟ چیشو نفهمیدین ؟ نکته خاصی نداره که !!
بازم من نفهمیدم...
فکر کنم منظورشون اینه که اسم توابع و نوع پارامتراشون و ... تو فایل h. میریزین
بدنه اصلی توابع و کلاسها که همون کدهاشون میشه رو هم تو فایل cpp. میریزین
البته اینارو دوستمون هم گفتم حالا ما یکم جمله بندیشو تغییر دادیم شاید بفهمید.
---------------------------
جناب sin2x=2sinxcosx به کارتون ادامه بدین ما هم داریم با اینا پیش میریم ببینیم آخر این ++C رو یاد می گیریم یا نه
راستی یکی از مثالاتون شبیه یه سوال امتحانیمون بود:19: ، نکنه طراح سوالای ما بودین:46:
جمله بندیتون هم خیلی باحاله، این جملتون رو میگم:31: :31:
تو ارث بري هم ميگيم فلان يه فلان است .
ara.look
01-08-2009, 14:41
فکر کنم منظورشون اینه که اسم توابع و نوع پارامتراشون و ... تو فایل h. میریزین
بدنه اصلی توابع و کلاسها که همون کدهاشون میشه رو هم تو فایل cpp. میریزین
البته اینارو دوستمون هم گفتم حالا ما یکم جمله بندیشو تغییر دادیم شاید بفهمید.
---------------------------
سوال من اینجاست که چرا این کار میکنن؟
sin2x=2sinxcosx
01-08-2009, 14:44
جمله بندیتون هم خیلی باحاله، این جملتون رو میگم:31: :31:
با عرض سلام و تشکر .
منظورم از فلان یه فلان است این بود که مثلا اگه دو تا کلاس به نام های base و derived داشته باشیم و کلاس derived از کلاس base به ارث رسیده باشد ، در این صورت میگیم : derived یه base است .
ولی تو Composition میگیم : فلان یه فلان دارد .:20:
سوال من اینجاست که چرا این کار میکنن؟
در این مورد هم توضیح دادم :
2- اتفاقا اين کلاس رو به دو فايل h. و cpp. تبديل مي کنيم تا مفهوم شيء گرايي حفظ بشه . به کاربري که قصد استفاده از اين کلاس ما رو داره فقط فايل هدر داده ميشه که فقط اينو بدونه که اين کلاس ما چه توابعي دارن و چه آرگومان هايي مي گيرن . با ارائه توضيحات در فايل هدر توسط برنامه نويس کلاس ، ميشه بهتر کاربر برنامه نويس تابع main رو در جهت استفاده از کلاس راهنمايي کرد . فايل کامپايل شده فايل cpp کلاس هم به مشتري يا همون استفاده کننده از کلاس داده ميشه که بتونه به فايل h. پيوند بزنه . Source فايل cpp نبايد در دسترس مشتري قرار بگيره و اين همون مفهوم کپسوله سازي و مهندسي نرم افزار و تکنولوژي شيء گراييه که مشتري نبايد از چگونگي پياده سازي توابع اطلاع داشته باشه . فقط کافيه بدونه که چه توابعي وجود دارن و اين توابع چيکار مي کنن . ديگه لازم نيست بدونه که چه الگوريتمي براي انجام اين کار پياده سازي شده .
در مورد اين هم که هر کس فايل هدر رو داشته باشه مي تونه فايل cpp رو از روي اون بنويسه ، بايد بگم که خوب بنويسه . چه اشکالي داره . مهم اينه که به پياده سازي مدنظر ما لطمه وارد نشه .
من هم ان شاءالله پست بعدیم راجع به Operator Overloading خواهد بود . دارم الان آماده می کنم .
sin2x=2sinxcosx
01-08-2009, 15:15
خوب حالا پس از مدت ها : سربارگذاری عملگر یا Operator Overloading
سربارگذاری همون طوری که از اسمش مشخصه یعنی گذاشتن بار اضافی . همین کلمه اضافی و درک اون تو مفهوم سربارگذاری خیلی مهمه . :20: بعدا میگم یعنی چی . پس سربارگذاری عملگر میشه گذاشتن بار اضافی روی عملگر .
فرض کنین ما یه کلاس تعریف کردیم به اسم HugeInteger . این کلاس ، کلاس معروفی هست که کاربر می تونه ایجاد کنه تا محدودیت های نوع داده int رو جبران کنه . نوع داده int فکر کنم حداکثر تا 12 رقم پشتیبانی می کنه . با پیاده سازی کلاس HugeInteger میشه کلاس ( یا نوع داده جدیدی ) ایجاد کرد که تا بی نهایت رقم پشتیبانی کنه .
خوب فرض کنین ما برای این کلاسمون یه تابع عضو تعریف کردیم که عمل جمع رو بین دو تا شیء HugeInteger انجام میده . با فراخوانی این تابع به صورت مثلا زیر می تونیم این کارو انجام بدیم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
یعنی به تابع sum موجود تو کلاسمون ، دو تا شیء HugeInteger به نام های h1 و h2 می فرستیم و این تابع این دو تا رو جمع می کنه و نتیجه رو در قالب یه شیء HugeInteger دیگه به ما برمی گردونه .
ولی وقتی می خوایم دو تا int رو با هم جمع کنیم چیکار می کنیم ؟ خیلی راحت می نویسیم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ولی اگه بخوایم از عملگر + برای یه نوع داده ای ، غیر از انواع داده اصلی ( int, double, float, long ) مثلا برای کلاس HugeInteger استفاده کنیم از جانب Compiler اروری با این مضمون دریافت می کنیم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ولی ما دوست داریم از این عملگر برای کلاس خودمون بین دو تا شیء HugeInteger استفاده کنیم . برای این کار باید ما عملگر + رو برای کلاسمون سربارگذاری کنیم و این مفهوم سربارگذاری عملگر هست .
چند نکته در مورد سربارگذاری عملگر ها :
1- با سربارگذاری نمی توان عملگرهای جدید ایجاد کرد . فقط عملگرهای موجود را می توان سربارگذاری کرد .
2- با سربارگذاری یک عملگر ، عملگر مربوطه علاوه بر اینکه بین انواع داده ای اصلی مثل int تعریف شده است ، برای کلاس موردنظر ما هم تعریف شده خواهد بود . یعنی با سربارگذاری یک عملگر برای یک کلاس ، آن عملگر باز هم به وظیفه های قبلی خود در مورد انواع داده ای دیگر آشنا است . ( همون مفهوم کلمه بار اضافی اینجا بود . )
3- چهار عملگر وجود دارد که نمی توان آن ها را سربارگذاری کرد :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
بقیه عملگر ها قابل سربارگذاری هستند . حتی عملگرهای new و delete .
4- دو عملگر زیر تنها عملگرهایی هستند که قادرند بدون سربارگذاری با هر نوع داده ای بکار روند :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مرسی.
ولی کاش 1 خط کد هم می نوشتید که چجوری باید سربارگذاری کرد!
آخه این فقط شد تعریفش!
منبع : Prentice.Hall.C.plus.plus.How.to.Program.5th.Editi on.Jan.2005.INTERNAL
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
1 // Fig. 11.4: PhoneNumber.cpp
2 // Overloaded stream insertion and stream extraction operators
3 // for class PhoneNumber.
4 #include <iomanip>
5 using std::setw;
6
7 #include "PhoneNumber.h"
8
9 // overloaded stream insertion operator; cannot be
10 // a member function if we would like to invoke it with
11 // cout << somePhoneNumber;
12 ostream &operator<<( ostream &output, const PhoneNumber &number )
13 {
14 output << "(" << number.areaCode << ") "
15 << number.exchange << "-" << number.line;
16 return output; // enables cout << a << b << c;
17 } // end function operator<<
18
19 // overloaded stream extraction operator; cannot be
20 // a member function if we would like to invoke it with
21 // cin >> somePhoneNumber;
22 istream &operator>>( istream &input, PhoneNumber &number )
23 {
24 input.ignore(); // skip (
25 input >> setw( 3 ) >> number.areaCode; // input area code
26 input.ignore( 2 ); // skip ) and space
27 input >> setw( 3 ) >> number.exchange; // input exchange
28 input.ignore(); // skip dash (-)
29 input >> setw( 4 ) >> number.line; // input line
30 return input; // enables cin >> a >> b >> c;
31 } // end function operator>>
[/CODE]
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
Overloading Unary Operators
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
Overloading Binary Operators
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
Overloading ++ and --
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ممنون ها آبجی، ولی 1 کم نا مفهوم بود!
آخه زبان شیرین پارسی رو ول کردید، به زبان خارجه (:27:) نوشتید، اون هم با نظم کم و ...
تقریباً فهمیدم مطلب چیه.
ولی اگر فارسی توضیح بدید، حداقل برای تازه کار ها بهتره.
ممنون از لطفتون
ممنون ها آبجی، ولی 1 کم نا مفهوم بود!
آخه زبان شیرین پارسی رو ول کردید، به زبان خارجه (:27:) نوشتید، اون هم با نظم کم و ...
تقریباً فهمیدم مطلب چیه.
ولی اگر فارسی توضیح بدید، حداقل برای تازه کار ها بهتره.
ممنون از لطفتون
توضیح با استاده ما که طلبه ایم هوچی بلد نیستیم:46:
sin2x=2sinxcosx
01-08-2009, 21:19
کد رو که حتما مفصل مي ذارم . اين فقط براي آشنايي بود . براي اکثر عملگر ها کد مي ذارم حتما .
sin2x=2sinxcosx
01-08-2009, 21:23
توضیح با استاده ما که طلبه ایم هوچی بلد نیستیم:46:
خيلي ممنون بابت مثال ها . ولي شما که دست ما رو ، رو کردين !! :31: من مي خواستم مثال هامو از کتاب ديتل بذارم که اونا رو هم شما زحمت کشيدين گذاشتين .
ولي باز هم ممنون . :20:
sin2x=2sinxcosx
01-08-2009, 23:01
خوب ...
يه مثال مي زنم براي 10 عملگر . براي بقيه هم انشاءالله تو پست هاي بعدي .
براي عمگلرهاي :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه مثال خيلي ساده . کلاس Rational . اعداد گويا . مي دونين که تو ++C چنين نوع داده اي وجود نداره . ما ايجاد مي کنيم و اين 10 عملگر رو براش سربارگذاري مي کنيم .
اين هدر تابعه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در مورد سربارگذاري << و >> فعلا چيزي نمي گم . فقط يه کم نگاهشون کنين . تو پست هاي بعدي ان شاءالله . دو سه سطر نوشتم ديدم نه هنوز خيلي هم مونده . پاکشون کردم و به جاش اين جملات رو دارم مي نويسم. :46:
اي کاش در مورد اين سوال بپرسين و من جواب بدم . واقعا نمي دونم چجوري بگم . ( کلا از اولش هم ارائه مطلب من ضعيف بوده . :41: )
با نگاه به هدر کلاس مي بينيم اين کلاسمون حاوي يه سازنده ، يه تابع عضو به نام simple که بعدا مي بينين چيکار مي کنه و چهار تابع عضو براي سربارگذاري عملگرهاي مربوطه . دو تا هم داده عضو داريم که اولي صورت کسر و دومي مخرج کسر رو ذخيره مي کنه .
اين هم Implementation کلاس :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
سازنده مون به صورت مقدار 0 و به مخرج مقدار 1 ميده .
اين کلاس رو خودم اون زمان ها که استاد براي تمرين خواسته بود نوشتم . بنابراين تابع simple ام رو زياد جدي نگيرين . يه کم پياده سازيش اين جوريه :weird: . استاد مي گفت بايد يه تابع ديگه مي نوشتين براي کوچکترين مخرج و مشترک ، ولي من ننوشتم . کاملا گنگه . اين تابع به طور مثال عدد گوياي شش نهم رو مي کنه دو سوم . ربطي به سربارگذاري نداره . بي خيالش شين . :20:
حالا مي رسيم به سربارگذاري عملگر + . تابع سربارگذاري اين عملگر ، يه Rational مي گيره و با شيء this جمع مي کنه و يه Rational بر مي گردونه !!
عملگر + يه عملگر دودويي يا Binary هست . يعني دو عملوند ميگيره . يکيش تو سمت چپ و يکيش تو سمت راست . عملوند سمت راست رو به تابع از طريق آرگومان مي فرستيم ( r ) و عملوند سمت چپ هم به قول استادمون "خودش" هست . يعني this . يعني داده هاي عضو همون شيئي که اين تابع رو فراخواني کرده . در مثال بالا denominator همون this->denominator هست که ما از عملگر this به طور صريح استفاده نکرديم ولي Compiler به طور ضمني اون رو به کار مي گيره . نمي دونم تونستم 50 درصد مطلب رو برسونم يا نه ... :41:
يه شيء به اسم temp به طور موقت مي گيريم و نتيجه جمع رو تو اون ذخيره مي کنيم و temp رو برميگردونيم .
البته قبلش صورت و مخرج رو براي ساده سازي به تابع simple مي فرستيم .
سربارگذاري - و * و / هم به همين صورته .
حالا بعد از سربارگذاري عملگرهاي + و - و * و / ، سربارگذاري =+ و =- و =* و =/ به يه خط کد نياز دارن .
من اينا رو به هدر کلاس اضافه مي کنم و همون جا هم پياده سازي مي کنم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اين داستان همچنان ادامه دارد .......................
sin2x=2sinxcosx
02-08-2009, 11:20
خوب حالا در مورد سربارگذاري عملگرهاي ورودي و خروجي يا همون << و >> :
براي اين قسمت سوال خيليه :
1- چرا خارج از کلاس تعريف شدن ؟ ( به صورت تابع Global يا سراسري )
2- چرا friend تعريف شدن ؟
3- چرا دو تا پارامتر مي گيرن ؟ ( بر خلاف ساير عملگرهاي دودويي که يه پارامتر مي گرفتن . )
4- چرا هم يه stream مي گيرن و هم يه stream برميگردونن ؟
5- چرا آدرس مي گيرن و برميگردونن ؟ ( & )
6- چرا براي ورودي ، شيئمون رو const تعريف نکرديم ولي براي خروجي const تعريف کرديم ؟
من به اين 6 سوال جواب ميدم . اگه باز هم سوال موند بگين تا بگم !
1- عملگر + به صورت تابع عضو تعريف شد . چون هر دو عملوند اون يه شيء از خود کلاس هستن . ولي در مورد عملگرهاي ورودي و خروجي ، يکي از اونا ( هميشه عملوند سمت چپ ) يه شيء از کلاس istream يا ostream هستن نه Rational . هميشه چنين عملگرهايي به صورت تابع سراسري تعريف ميشن .
2- براي اينکه بتونن به داده هاي عضو private کلاس دسترسي داشته باشن .
3- چون در مورد عملگري مثل + ، اين يک شيء از خود کلاس ( Rational ) است که تابع سربارگذاري شده رو احضارمي کنه . ولي در اينجا شيء cout يا cin اين کار رو انجام خواهد داد . پس از this اينجا خبري نيست و ما مجبوريم تنها شيء موجود رو براش بفرستيم .
4 و 5 - يه stream مي گيرن تا شيء cout يا cin تو اون قرار بگيره . و يه stream به صورت ارجاع ( & ) بر مي گردونن تا بشه از اين دو عملگر به صورت دنباله اي استفاده کرد . به شکل زير :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
در اين حالت نوع برگشتي cout << r1 ، يک cout خواهد بود و دوباره مي تواند به صورت cout << r2 ارزيابي شود و يه cout برگردانده شود تا در ادامه دستور رو به شکل زير داشته باشيم : cout << r3
حالا چرا آدرس مي گيرن ؟ :31:
اينو من بايد تو مبحث توابع مي گفتم . ولي ديدم همه دوست دارن بحث شيء گرايي شروع بشه و اين مطالب ديگه خسته کننده هستن . من هم نگفتم . حالا مجبورم اينجا بگم .
سه روش براي انتقال آرگومان به توابع وجود داره .
1- از طريق مقدار
2- از طريق ارجاع
3- از طريق ارجاع با اشاره گرها
1- همون روشي بود که تا حالا استفاده مي کرديم . يعني وقتي مي خواستيم چيزي رو به تابع پاس بديم يه کپي از اون ايجاد ميشد و به تابع فرستاده ميشد . در اين حالت اين تابع هر بلايي سر اين چيز ميوورد تو تابع فراخواننده تاثير نداشت . چون اون کپي اورجينالشو داره .
2- در اين حالت به جاي اينکه کپي چيز فرستاده بشه ، آدرس اون فرستاده ميشد . در اين حالت کپي نميشه . همون روشي که الان استفاده کرديم . در اين حالت ديگه هر گونه تغيير تو هر دو تابع دخالت داده ميشه . چون فقط آدرس کپي شده و فرستاده شده نه خود اون . يه مزيت هم که داره اينه که سرعت اجراي برنامه در اين حالت بالاست . چون ديگه قرار نيست چيزي کپي بشه .
حالت سوم هم مثل اوليه و فقط Syntax فرق مي کنه . در اين حالت پارامترهاي تابع يه اشاره گر هستن و ما آدرس رو به تابع مي فرستيم .
6- چون عملگر خروجي شيء رو تغيير نمي ده بنابراين بهتره const تعريف بشه ولي عملگر ورودي قراره شي رو تغيير بده . بنابراين نمي تونيم از const استفاده کنيم .
حالا در مورد خود سازوکار .
ما تو تابع main يه شيء به اسم r از کلاس Rational تعريف مي کنيم . بعد مي گيم cout << r . در اين حالت ، cout ميره به جاي out در پارامترهاي تابع ميشينه و r هم تو r . بنابراين دستورهاي خروجي رو با دستور out به جاي cout انجام ميديم و آخرسر اين out رو برميگردونيم .
باز هم ادامه دارد ...
sherlockholmz
02-08-2009, 16:19
با سلام
استاد آيا لطف خواهي كرد و pdf اين دروس را تهيه و لينك كني؟
قبلا" از لطف شما نهايت امتنان را دارم.
sin2x=2sinxcosx
02-08-2009, 19:47
با سلام
استاد آيا لطف خواهي كرد و pdf اين دروس را تهيه و لينك كني؟
قبلا" از لطف شما نهايت امتنان را دارم.
درود ...
ان شاءالله اگر عمري باقي بود و توفيقي از جانب پروردگار جهت ادامه حيات در اين دايره هستي نصيب اين جانب گرديد و بحث را توانست تا يه سمت و سويي کشاند و بحث شيء گرايي به اتمام رسيد ، اين PDF تنظيم ، و جهت دانلود شما بزرگواران لينک خواهد شد .
قبلا از حسن توجه حضرت عالي نهايت سپاس را دارم و از خداوند طول عمر و سلامت کامل را براي شما يار بزرگوار مسئلت دارم .
:20:
sin2x=2sinxcosx
03-08-2009, 20:30
سلام ...
نکته مهم ديگه اي که تو سربارگذاري هست ، سربارگذاري عملگر هاي ++ پيشوندي و پسوندي است . در اين مورد فکر کنم قبلا بحث شده که اين دو چه فرقي با هم دارن .
يه مثال خيلي خيلي ساده مي زنم . اين تعريف و پياده سازي کلاسمون :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
عملگر خروجي رو براي اين سربارگذاري کردم تا بتونم تو تابع main فرق دو عملگر پيشوندي و پسوندي يا Prefix و postfix رو نشون بدم . يه سازنده داريم که به تنها داده عضو ما که از نوع int هست مقدار صفر ميده . بعد پياده سازي تابع سربارگذاري ++ پيشوندي رو مي بينين . اين تابع يه ارجاع به کلاسمون برميگردنه و پارامتري نمي گيره . داخل تابع ، اول داده عضو مورد نظر خودمون رو يدونه ++ مي کنيم و بعد خود شيء رو به عنوان نتيجه برميگردونيم . حالا چجوري تابع سربارگذاري ++ پسوندي رو با اين متمايز کنيم ؟ کافيه در ليست پارامترها يه کلمه int بنويسيم . اين کلمه هيچ ارزشي نداره . مي بينين که يه متغير هم تعريف نکرديم و فقط int خالي نوشتيم . اين فقط براي اينه که اين دو تابع ++ از هم متمايز باشن . فقط نکته اي که تو سربارگذاري ++ پسوندي هست اينه که اول شيء خودمون رو تو يه شيء از نوع همون کلاس ذخيره مي کنيم . بعد خود شيء رو پلاس پلاس مي کنيم و بعد شيء پلاس پلاس نشده رو برمي گردونيم . فهميدين که چي شد ؟ :46:
اين هم تابع main براي تست نتيجه کار :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يه شيء به نام s از کلاسمون مي گيريم . بعد ++s رو چاپ مي کنيم . اول مي بينين که s چاپ ميشه ( يعني 0 ) و بعد s يدونه ++ ميشه . يعني ميشه 1 . بعد s++ رو چاپ مي کنيم . اول s يدونه ++ ميشه يعني ميشه 2 و بعد چاپ ميشه .
تقريبا سربارگذاري رو اينجا تموم مي کنم .
یه چیزی بگم ناراحت نمیشی؟!
1 کم کثیف کاری! :دی
یه دفعه تمام Operator ها رو ریختی وسط، یکی رو گفتی، میگی بقیه هم همچنین!
شما بگو تئوریش اینجوریه.
بعد این ها Operator های ممکن اینها هستند.
اصولاً باید اینجوری تعریفشون کرد.
این هم 1 مثال مربوط به این یه تیکه.
و ...
نه که یه پست بدی برای تئوری، بقیه اش هم همینجوری.
البته فکر می کنم عجله من کار شما رو خراب کرد!
+
شما هنوز نگفتی این istream و ostream چی هستند، ازشون تو مبحث Operator ها فراوون استفاده می کنی!
همین دیگه!
اگر همین Operator ها رو یه بار درست بگی، می بینی چه شاگرد خوب و بگیری هستم! :گل:
مرسی
sin2x=2sinxcosx
03-08-2009, 20:43
1 کم کثیف کاری! :دی
آقا خيلي ممنون . واقعا شرمنده کردين !! :20:
واقعا مطالب گنگ هستن ؟ تئوري رو که اول گفتم . با نگاه به مثال ها هم تقريبا ميشه فهميد قضيه چيه .
ولي خوب چون شما مي گين ، قبل از اينکه ارث بري رو شروع کنم يه بار ديگه در مورد اصول سربارگذاري مطالبي ميگم .
آخه يه کم عجله دارم . دو سه روز ديگه ميرم تا يه ماه بعد . مي خوام قبل از اينکه برم ، شيء گرايي رو تموم کنم .
sin2x=2sinxcosx
04-08-2009, 11:33
باز هم سلام .
اين دوستمون dogtag يه خورده از دستم ناراحت بودن که ... .
براي همين يه پست ديگه هم ميدم در مورد چطوري سربارگذاري کنيم .
خوب براي سربارگذاري هر عملگر يه تابع مي نويسيم . اسم اين تابع هميشه بايد از کلمه کليدي operator به اضافه عملگر مورد نظر تشکيل بشه . تنها نکته اي که مي مونه اينه که اين تابع چي بايد برگردونه و چي بايد بگيره . اين هم که تقريبا راحته . شما يه بار عملگر رو تو ذهن خودتون مجسم کنين و ببينين وقتي کاربر تو جايي مي نويسه h1 == h2 ، که h1 و h2 اشيائي از کلاس شما هستن ، مي خواد که نتيجه يا True باشه يا False . يعني تابع سربارگذاري ما نبايد چيزي غير از اين برگردونه . بنابراين ما مي تونيم از نوع داده اي bool که فقط مي تونه true و يا false رو تو خودش نگه داره به عنوان نوع داده برگشتي تابع سربارگذاري عملگر == استفاده کنيم . بعد تو پياده سازي هم معين کنيم که کي true برگردونده بشه و کي false . اين عملگر به دو تا عملوند نياز داره . يکيش که همون خود شيئي است که اين تابع رو فراخواني کرده ، يعني this و يکيشو هم از طريق آرگومان براش مي فرستيم . در مورد عملگر =! به همين طور . ولي يه چيزي . شما وقتي == رو سربارگذاري کردين ، ديگه لازم نيست =! رو هم دوباره سربارگذاري کنين . مي تونين تو پياده سازي =! راحت بنويسين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
يعني هر چي عملگر == برگردوند ، =! خلاف اون رو برگردونه . ( ! علامت نقيض تو ++C هست . )
از اين کارا تو سربارگذاري عملگرهاي < و > و => و =< هم استفاده کنين .
مثلا فرض کنين عملگر > رو سربارگذاري کردين . اين تابع هم نتيجه اش يا true هست يا false . بنابراين براي نوع داده برگشتي اين تابع از bool استفاده ميکنيم . مثل == هم يه آرگومان ميگيره از نوع شيئي از خود کلاس . اين تابع رو پياده سازي مي کنيم . حالا سه عملگر بعدي به صورت زير به سادگي قابل سربارگذاري هستن :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
حالا کاربر فرض کنين تو تابع main دو تا شيء به نام هاي h1 و h2 از کلاسمون گرفته و داره کاراي زير رو انجام ميده :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تو اولي ميگيم آيا h1 کمتر از h2 هست ؟ تو اين جا انگار h1 داره تابع > رو فراخواني ميکنه . پس this همون h1 هست . يعني تو عملگرهاي دودويي ، هميشه عملگر سمت چپ به جاي this قرار مي گيره .
تابع سربارگذاري > فراخواني ميشه و بر اساس پياده سازيش يکي از دو مقدار true يا false رو برمي گردونه . فرض کنين true برگردونده شده . يعني h1 کوچکتر از h2 هست . حالا ميره خط 2 و مي گه آيا h1 يا this بزرگتر از h2 هست ؟ سربارگذاري عملگر بزرگتر به ما ميگه که اين تابع نتيجه تابع h2 < *this رو برميگردونه . که اين تابع false بر ميگردونه . چون h2 بزرگتر از this يا h1 بود . در مورد h1<= h2 هم تابع سربارگذاري اين عملگر ، نقيض عملگر < رو برميگردونه . يعني اگه بزرگتر نباشه پس حتما کوچکتر يا مساوي هست و به همين ترتيب ... .
مثلا فرض کنين مي خواين عملگر = رو سربارگذاري کنين . اين عملگر بايد شيء سمت راست خودش رو تو شيء سمت چپ يا this کپي کنه . پس يه شيء از خود کلاس ميگيره و يه شيء از خود کلاس برمي گردونه .
ضمنا يه نکته :
از عملگر = ميشه بدون سربارگذاري براي هر شيئي از کلاس هامون استفاده کرد . اين عملگر به طور اتوماتيک تک تک داده هاي عضو کلاس مون رو کپي مي کنه . اين کار در بيشتر مواقع کار مدنظر ماست . ولي اين کار تو بعضي جاها خيلي خطرناکه . مثلا جايي که شما يه داده عضو اشاره گر داشته باشين . مي دونين که اشاره گر حاوي آدرس يه متغير هست . بنابراين موقع کپي شدن آدرس کپي ميشه و اين مي تونه بعدا مشکلاتي جدي بوجود بياره . ( چون دو تا متغير داراي يه آدرس تو حافظه ميشن . )
در مورد istream و ostream سوال پرسيدين که من قبلا در موردشون بحث کرده بودم . istream يه کلاسه که تو کتابخانه استاندارد ++C تعريف شده و عمليات ورودي از صفحه کليد رو کنترل مي کنه و ما مي تونيم ازش استفاده کنيم . ostream هم يه کلاسه که تو کتابخانه استاندارد ++C تعريف شده و عمليات خروجي رو کنترل مي کنه و ما مي تونيم ازش استفاده کنيم . وقتي مي خوايم عملگرهاي ورودي و خروجي ( << و >> ) رو سربارگذاري کنيم ، اين توابع بايد يه istream يا ostream برگردونن .
ديگه نمي دونم باز هم مطالب گنگ هستن يا نه . ولي اگه گنگه باز هم بگين . من در خدمت هستم . :40:
این دفعه خـــیــــلــــی عالی گفتید.
واقعاً مرسی.
فقط اگر دلتون خواست، اون >> و << رو هم که قبلاً گفته بودید، با همین بیان، مطرح کنید.
(البته فکر کنم با این توضیحات، الان اونها رو بخونم، 100% بفهمم)
دوباره ممنون
sin2x=2sinxcosx
04-08-2009, 15:51
ممنون دوست عزيز .
در مورد << و >> ؟ :20:
باشه . هميشه حق با مشتريه . :20: ميگم . با اينکه قبلا يه پست بهش اختصاص داده بودم .
iostream يه کتابخانه است . اون رو include مي کنيم تا بتونيم از قابليت ها ورودي و خروجي که با سخت افزار درگير هستن به راحتي استفاده کنيم . کتابخانه مجموعه اي از کلاس هاي از پيش تعريف شده هست . :46:
istream و ostream هر کدوم يه کلاس از اين کتابخانه هستن .
cout و cin دو تا شيء به ترتيب از کلاس هاي ostream و istream هستن که اين شيءها هم از قبل تعريف شده هستن .
ما مي خوايم عملگرهاي << و >> براي کلاسمون سربارگذاري کنيم . مجبوريم از اين کلاس هاي istream و ostream استفاده کنيم تا بتونيم يه چيزي رو از صفحه کليد بگيريم و يا يه چيزي رو تو صفحه نمايش چاپ کنيم . ما وقتي مي نويسيم cout << h1 ، شيء cout تابع سربارگذاري ما رو احضار مي کنه . ولي cout که شيئي از کلاس ما ( HugeInt ) نيست که ! :46: يه شيء از کلاس ostream هست . پس this اينجا وجود نداره . بنابراين ما تابع سربارگذاري اين تابع رو داخل کلاس نمي ذاريم . يعني تابع سربارگذاري عملگر خروجي يه تابع عضو نيست . يه تابع سراسري يا Global هست که خارج از کلاس تعريف ميشه . ولي ما چرا داخل کلاس استفاده کرديم ؟ براي اينکه به کلاس نشون بديم اين تابع دوست ما هست و مي تونه به داده هاي private ما دسترسي داشته باشه . و اعلان friend رو در اولشون آورديم . اين عملگرهاي << و >> هم يه عملگر دودويي هستن . قبلا وقتي مي خواستيم يه عملگر دودويي مثل + رو سربارگذاري کنيم ، مي گفتيم يکي از عملوندها this يا همون شيئي که اين تابع رو فراخواني کرده و شيء ديگه ( شيء سمت راست ) رو هم براي تابع مي فرستاديم . ولي اينجا ما this نداريم . this ما هميشه عملوند سمت چپ مي شد . ولي اينجا که عملگر سمت چپ ما اصلا يه شيء از کلاس ما نيست . عملوند سمت چپ ما cout هست که شيئي از کلاس ostream هست . بنابراين مجبوريم هر دو عملوند رو براي تابع سربارگذاري بفرستيم . مثلا تو کلاس Rational که قبلا مثال زده بودم ، يه شيء به اسم out از کلاس ostream براي تابع سربارگذاري فرستاده بوديم و يه شيء هم از خود کلاسمون . اين تابع يه ostream هم برميگردونه تا داخل cout بذاره و نتيجه چاپ بشه . در مورد istream هم همين طور .
ولي باز هم اگه مشکلي هست خواهشا بپرسين . تا وقتي شما اجازه ندادين من ارث بري رو شروع نمي کنم .
از پشتکارتون خوشم مياد . اگه شما و امثال شما نبودن ، روحيه اي براي ادامه در بنده نمي موند .
ولي اينو هم بدونين که تو هيچ کتابي اين همه به سربارگذاري اين دو عملگر پرداخته نشده . :20:
معمولا يه مثال زدن گفتن يه istream براش مي فرستيم و يه شيء از کلاس خودمون و تمام . نمونه اش کتاب ديتل که اولين مرجع درس برنامه نويسي پيشرفته براي دانشجويان کشور و البته خارج از کشور .
موفق باشين ...
خیلی ممنون.
خوب بود.
اجازه ما دست شماست.
مشتاقانه منتظر ادامه مطلب هستم.
sin2x=2sinxcosx
04-08-2009, 19:56
آقا يه نکته ديگه در مورد سربارگذاري .
فرض کنين h يه شيء از کلاس HugeInt هست . مي نويسيم cout << h ، در واقع کار فراخواني تابع >>operator رو به صورت زير انجام ميديم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
ولي وقتي مثلا ميگيم h1 + h2 که h1 و h2 دو شيء از کلاس HugeInt هستن ، در واقع اين فراخواني انجام ميشه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید :46:
sin2x=2sinxcosx
05-08-2009, 10:58
سلام ...
ارث بري !!
تقريبا ميشه گفت مهمترين مبحث تکنولوژي شيء گرايي ، مبحث ارث بري هست . البته به نظر من ساده ترين هم هست . ( اگه خودتون مقايسه کنين مي بينين واقعا به نسبت خيلي ساده اس . )
بدون حاشيه شروع مي کنيم .
ضمنا من اين پست رو به تئوري اختصاص مي دم . بعدا نگين مثال چرا نگفتي . مثال بعدا مي زنم .
تعريف جامع و زيباي پروفسور ديتل رو از ارث بري اول ببينين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اگه به کلمه کلمه اين تعريف دقت کنين واقعا توضيحات ارث بري تموم شد . فقط مي مونه اين که يه کم Syntax ياد بگيرين .
ارث بري نوعي استفاده مجدد از نرم افزار ( Source نرم افزار ) هست که برنامه نويس داده ها و رفتارهاي ( Attributes & Behavior ) کلاس موجود را در اختيار مي گيرد و به آن قابليت هاي جديدي مي افزايد .
اين هم ترجمه طلبه sin2x=2sinxcosx از جمله پروفسور ديتل بود . :20:
فرض کنين يه کلاس داريم که وسيله نقليه رو شبيه سازي کرده و داده ها و توابع عضو اون رو تعريف کرديم .
اين وسيله نقليه ما چهار عدد چرخ داره . يدونه فرمان داره . دنده داره . يه رنگ داره . هر کدوم براي اين وسيله نقليه يه خصيصه يا Attribute هستن . ( يه داده عضو )
اين وسيله نقليه مي تونه حرکت کنه و بايسته و يا دور يزنه . هر کدوم براش يه رفتار يا Behavior هستن . ( يه تابع عضو )
بعد فرض کنين يه اتومبيل هم داريم به اسم fghijkl . فرض کنين اين اتومبيل هم چهار چرخ داره . فرمان و دنده داره . رنگ هم داره . فرض کنين اين اتومبيل در حالت خاص تر يه چرخ هم زير ماشين اون وسط داره که اتومبيل مي تونه روي اون چرخ بلند بشه و فقط به کمک اين چرخ حرکت کنه . اين اتومبيل هم مي تونه حرکت کنه و بايسته و دور بزنه .
مي بينين که اتومبيل fghijkl همه خصوصيات و رفتارهاي يک وسيله نقليه رو داره به اضافه يه خصوصيت جديد و يک رفتار جديد . يه چرخ اضافي و رفتار جديد هم اينکه مي تونه روي يه چرخ بايسته .
ما کلاس وسيله نقليه رو شبيه سازي کرديم و داده هاي عضوش رو مشخص کرديم و توابع عضوش رو هم به طور کامل پياده سازي کرديم . حالا مي خوايم کلاس fghijkl رو پياده سازي کنيم . آيا بايد دوباره عمليات حرکت کردن و ايستادن و دور زدن و همچنين داده هاي چرخ و فرمان و ... رو براش پياده سازي کنيم ؟
نخير . با يه ارث بري از کلاس وسيله نقليه مشکل حل خواهد شد .
در اين حالت مي گيم fghijkl يک وسيله نقليه است . کلاس fghijkl توابع و داده هاي کلاس وسيله نقليه رو به ارث مي بره . حالا مي تونه اون توابع رو با کمي تغيير براي خودش استفاده کنه و يا اگه هم تعريف نکرد دقيقا هموني که تو کلاس وسيله نقليه هست اجرا مي کنه . فقط کافيه يه داده عضو ( همون يه چرخ وسطي ) اضافه بشه + يه رفتار ( ايستادن روي يک چرخ و ... )
حالا برگردين و جمله ديتل رو يه بار ديگه بخونين .
sin2x=2sinxcosx
05-08-2009, 17:00
سلام دوستان عزيز ...
بنده قراره اگه خدا بخواد فردا برم مسافرت و تا شروع ماه مبارک رمضان در خدمت نيستم . ببخشيد بحث نيمه کاره موند . اگه مي دونستم پنج شنبه مي رم يا ارث بري رو شروع نمي کردم و يا اگه شروع مي کردم تمومش مي کردم و بعد مي رفتم . الان هم ببخشيد متاسفانه اصلا وقت ندارم و دارم مي رم بيرون براي خريد و اينا . فقط يه بار ساعت 12 شب مي تونم بيام . اون موقع اگه خوابم نيومد ميام تمومش مي کنم .
موفق باشين ......................... :40:
sin2x=2sinxcosx
05-08-2009, 21:38
خوب اومدم که تموم کنم برم .
قبل از شروع مثال براي ارث بري لازمه که با يه access specifier يا مشخصه دسترسي ديگه آشنا بشين .
مشخصه دسترسي protected . هر گاه يه داده يا يه تابعي در کلاس پايه به صورت protected تعريف بشه ، تو کلاس هاي مشتق شده ( به ارث رسيده) از اون کلاس پايه ميشه به طور مستقيم بهش دسترسي داشت . ولي هر جايي غير از اين جا مثلا تو تابع main نميشه .
به عضو private تعريف شده در کلاس پايه نميشه از کلاس هاي مشتق يا هر جاي ديگه اي دسترسي داشت .
به عضو public ميشه هم تو کلاس هاي مشتق و هم تو کلاسها و توابع ديگه دسترسي داشت .
البته سه نوع ارث بري داريم : public و protected و private . ما فعلا هميشه از ارث بري public استفاده خواهيم کرد . يعني متداول ترين نوع همين public هست .
اين مثال رو ببينين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدهدر کلاس Account رو ببينين . يه سازنده داره و سه تا تابع عضو و يه داده عضو .
بعد اونو تو قطعه کد دوم پياده سازي کرديم .
تو قطعه کد سوم هدر کلاس SavingsAccount رو مي بينين که از کلاس پايه Account به ارث رسيده ( مشتق شده ) . نياز به توضيح نيست . مي بينين که بعد از تعريف کلاس علامت دو نقطه گذاشتيم و گفتيم که از کلاس Account به طور public مشتق شده . و مي بينين که کلاس پايه ( Base Class ) رو هم تو کلاس مشتق ( Derived Class ) توسط دستور include اورديم . اين کلاس سه تابع عضو کلاس Account و يه داده عضو اونو به ارث برده به اضافه يه تابع عضو و يک داده عضو که خودش اضافي داره .
يه نکته اي هم که هست اينه که هيچ وقت Constructor به ارث نمي رسه . هميشه بايد براي هر کلاس به طور مجزا تعريفش کنين .
تو تعريف کلاس مشتق هم مي بينين که تو پياده سازي سازنده ، سازنده کلاس پايه رو هم احضار کرديم .
يه نکته ديگه . ميشد توابعي که تو کلاس پايه هستن ، تو کلاس مشتق يه طور ديگه پياده سازي کرد . به اين کار ؛ Override کردن تابع ميگن . در اين صورت دو تا تابع همنام خواهيم داشت که دو پياده سازي متفاوت دارن . براي اجراي يک تابع مورد نظر که Override شده ، از نام کلاس به اضافه دو تا دونقطه به اضافه اسم تابع استفاده مي کنيم.
مثلا فرض کنين ما تابع credit رو تو کلاس مشتق هم پياده سازي کرديم . حالا مي خوايم تابع credit کلاس پايه رو فراخواني کنيم . اين کارو مي کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
تا اون جايي که من مي دونم تموم شد .
تا ساعت 12 هستم . اگه موردي هست بگين . اگه نه هم که به خدا مي سپارمتون ...
:40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40: :40:
ara.look
05-08-2009, 23:40
تفاوت int با long int چیست
sin2x=2sinxcosx
06-08-2009, 00:01
تفاوت int با long int چیست
تو کامپايلرهاي جديد هيچي . يعني همه اينا يکين :
int و long و long int .
اگه از عملگر sizeof براي هر کدوم استفاده کنين مي بينين که همشون 4 بايت حافظه مي گيرن .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مونا خانوم، (حدس زدم! :دی) شما هم که کثیف کار تر از همه! :دی
خب همین رو بهش 1 نظم می دادید، می شد یه پست 100% مفید.
البته این هم 80% مفیده.
ممنون از این که گذاشتید.
[ برای مشاهده لینک ، لطفا با نام کاربری خود وارد شوید یا ثبت نام کنید ]
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
اگه میتونی 10 مگ دانلود کنی بگو تا خود کتابو بذارم تا کثیف کاری نشه :دی
شکر خدا یه 128 دارم که گاهی اوقات قاطی می کنه و میشه 512!
ولی اگر 56K ذغالی هم داشتم، 10 مگ چیزی نبود!
مرسی
sin2x=2sinxcosx
17-08-2009, 09:13
Polymorphism
چندريختي يا Polymorphism در واقع نوعي استفاده از قابليت ارث بري در برنامه نويسي شيء گرا است .
کلاس پايه Animal رو در نظر بگيرين . سه کلاس Fish ، Frog و Bird از اين کلاس به ارث رسيدن ( مشتق شدن ) . مي خوايم براي حرکت اين حيوانات برنامه اي بنويسيم . هر حيوان ( قورباغه ، ماهي و پرنده ) حرکت خاص خودشو داره . مثلا قورباغه براي حرکت مي پره ، ماهي شنا مي کنه و پرنده پرواز مي کنه . کلاس Animal هم فرض کنيد راه مي ره . هر چهار تاي اين کلاس ها داراي تابع عضوي به نام move هستن .
مي خوايم براي اين تابع از خاصيت چندريختي استفاده کنيم . براي اين منظور بايد قبل از نوع داده برگشتي اين تابع کلمه virtual رو قرار بديم . مثلا :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبراي استفاده از چندريختي ، يه اشاره گر به کلاس پايه تعريف مي کنيم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدحالا مي تونيم آدرس کلاس مشتق رو تو اشاره گر کلاس پايه قرار بديم . به شکل زير :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدحالا اگه تابع move کلاس پايه رو فراخواني کنيم ، تابع move مربوط به کلاس قورباغه احضار ميشه .
اما اگه از کلمه کليدي virtual استفاده نکرده بوديم ، کماکان تابع move کلاس Animal احضار مي شد . استفاده از کلمه virtual به کامپايلر ميگه که در زمان اجرا تعيين کنه که کدوم اشاره گر حاوي چه آدرسي هست نه در زمان کامپايل .
به تابع move مي گيم تابع مجازي يا virtual . يه مفهوم ديگه هم که تو Polymorphism وجود داره ، مجازي محض يا pure virtual هست . با يه مثال اينو هم توضيح مي دم .
فرض کنين داريم يه برنامه براي بازي شطرنج مي نويسيم . اسب و فيل و سرباز و ... همه از کلاس پايه اي به نام Mohreh به ارث رسيدن . هر کدوم از کلاس هاي اسب و فيل و سرباز و ... داراي تابع move منحصر بفرد هستن . چون شيوه حرکت هيچ مهره اي شبيه به هم نيست . ولي کلاس پايه ما هم داراي تابع move هست . براي اين کلاس چجوري تابع move رو پياده سازي کنيم ؟ معلوم نيست که منظور از Mohreh چيه . حرکتي براي اين کلاس نمي تونيم تعيين کنيم . بنابراين بايد تابع move رو pure virtual تعريف کنيم . کافيه در کلاس پايه ، تابع move رو مساوي صفر قرار بديم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیداين تابع رو ديگه پياده سازي نمي کنيم .
نکته : به هر کلاسي که حداقل يه تابع مجازي محض داشته باشه ميگيم کلاس تجريدي يا Abstract Class . از کلاس تجريدي نمي توان شيئي نمونه سازي کرد .
اين Polymorphism خيلي کاربرد داره . مثلا من قبلا که داشتم پروژه شطرنج رو مي نوشتم اين چندريختي خيلي کمک کرد . بدون اون يه کم سخته . همچنين باعث ميشه ظاهر برنامه استاندارد به نظر برسه .
تو پست بعدي مثال هم ميارم . ! جناب dogtag ! :20:
sin2x=2sinxcosx
19-08-2009, 20:57
ببخشيد که اين روزا کم ميام و فاصله بين پست ها زياد ميشه .
فکر کنم قبلا کلاس Account رو براي ارث بري مثال زده بودم . حالا هم اونو تغيير دادم براي Polymorphism .
اول کد برنامه رو مي ذارم بعد يه چيزايي شبيه توضيح مي دم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدخوب ...
:20:
بله ..... اولين قطعه کد ، هدر کلاس پايه مون هست . چهار تا تابع عضو داره . اولي Constructor هست که يه پارامتر از نوع double داره . بعد سه تا تابع ديگه داره که اولي Virtual و دو تاي بعدي pure virtual هستن . يدونه هم داده عضو داره که به صورت protected تعريف شده تا توسط کلاس هاي مشتق از اين کلاس ، يعني SavingsAccount قابل دسترسي باشه . قطعه کد بعدي پياده سازي اين کلاس رو نشون ميده . مي بينين که توابع pure virtual پياده سازي نشدن .
قطعه کد سوم هدر يه کلاس به نام SavingsAccount هست که از کلاس Account به ارث رسيده . يه سازنده داره .
دو تا نکته اين جا هست . يکيش اينه که مي بينين توابع credit و debit و print دوباره تو کلاس مشتق پياده سازي شدن . به اين کار Override کردن تابع مي گن . نکته دوم اينه که گذاشتن کلمه کليدي virtual در کنار توابع عضو کلاس مشتق اختياره . چون تو کلاس پايه اين کار انجام شده و تا آخر اين توابع virtual تعريف شدن . اين کلاس دو تا تابع عضو اضافي + يه داده عضو ديگه داره . قطعه کد بعدي پياده سازي اين کلاس رو نشون مي ده .
........
حالا کار تو تابع main هستش .
ببينين کلاس Account ما يه کلاس Abstract هست .
چرا ؟
آفرين ... چون حداقل يه تابع pure virtual داره . بنابراين نمي تونيم ازش شيئي بگيريم .
ما قراره آدرس هاي اشياء کلاس مشتق رو تو اشاره گر هاي کلاس پايه قرار بديم و از طريق اين اشاره گر ها توابع کلاس مشتق رو فراخواني کنيم .
من در اينجا از vector استفاده کردم تا با اون هم آشنا بشين . براي استفاده از vector ، اونو اول include مي کنيم .
يه شيء از کلاس مشتق نمونه سازي مي کنيم . ( توجه داريد که کلاس مشتق ما Abstract نيست . ) دستور خط بعدي آرايه اي از اشاره گرهاي کلاس پايه رو ايجاد ميکنه . ما اينجا آرايه رو يک عضوي در نظر گرفتيم . بعد آدرس کلاس مشتق رو درون اشاره گر کلاس پايه قرار ميديم و توابع عضو credit و debit و print رو فراخواني مي کنيم . در اينجا توابع مربوط به کلاس مشتق فراخواني ميشه .
sin2x=2sinxcosx
21-08-2009, 11:28
با سلام خدمت دوستان عزيز و محترمي که تا اينجا ما رو همراهي کردن و هر کدوم به نحوي روحيه ادامه رو در بنده تقويت کردن .
قبلا يه فهرستي به پيشنهاد جناب CppBuilder2006 داده بودم . فقط نمي دونم چرا يادم رفته بود و template ها رو نذاشته بودم . ولي من اينجا در مورد اون هم توضيح مي دم . اگه template ها رو هم بگم بنا به عهدي که گذاشته بوديم مطالب زير مي مونه ( با توجه به اينکه قبلا راجع به اشاره گرها بحث شده بود ) :
1- توابع بازگشتي
2- کار با فايل ها
3- ساختمان داده ها
4- کلاس string
Template يا قالب
يه قالب تابعي داريم يه قالب کلاسي .
حالا اصلا قالب يا Template چي هست ؟
مثلا فرض کنين يه تابع داريم که يه آرايه از int ها رو مي گيره و ميانگين اونا رو به صورت يه int ديگه برمي گردونه . خوب حالا اگه براي اين تابع ما يه نوع داده ديگه غير از int بفرستيم ، مثلا double ، اين تابع نمي تونه کارشو انجام بده . يعني اين تابع ما فقط براي نوع خاصي از داده ها جواب مي ده . براي اينکه اين تابع براي همه انواع داده اي جواب داشته باشه از قالب ها استفاده مي کنيم . يه مثال کوچولو مي زنم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدتو سطر سوم اين قطعه کد دو کلمه کليدي template و typename رو ميبينين . وقتي قبل از يه تابعي از اين خط استفاده کنيم به کامپايلر ميگيم که تابع مربوطه حاوي يه نوع داده اي قالبي به نام arrTemp هست . به جاي typename مي تونيم از کلمه کليدي class نيز استفاده کنيم . يعني دو خط زير هيچ فرقي با هم ندارن :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبعد تو تابع هم مي بينين که به جاي استفاده از نوع داده اي خاص از arrTemp استفاده کرديم . تو تابع main هم انواع مختلف داده اي رو براي تابع average فرستاديم و براي ما جواب آورده .
اين يه مثال براي قالب تابعي بود .
حالا در مورد قالب کلاسي :
اول يه مثال مي زنم . به طريقه استفاده از قالب در مورد اين کلاس توجه کنين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیداول از همه قالب کلاس T رو براي کل کلاس تعريف کرديم .
بعد تعريف کلاس و Constructor و Destructor رو مي بينين .
تابع push و pop رو مي بينين . توابعي که به ترتيب مقداري رو در پشته يا Stack مي ذارن و برميدارن .چون از قالب ها مي خوايم استفاده کنيم و اين مقداري رو که مي ذاريم و برميدارم همه انواع داده اي رو ساپورت کنه از قالب T استفاده ميکنيم . تو قسمت داده هاي عضو هم يه اشاره گر مي بينين که از نوع T تعريف شده . دليل چيه ؟
ببينين اين Stack ما آرايه اي رو شامل مي شه که سايز اون در زمان اجرا توسط کاربر تعيين ميشه . بنابراين ما نياز به يه اشاره گر داريم که ازش براي تخصيص پوياي حافظه استفاده کنيم . چون مي خوايم اين آرايه همه انواع داده اي رو پشتيباني کنه باز از T استفاده مي کنيم . توجه داريد که داده هاي عضو size و pop هميشه يه عدد صحيح رو ذخيره مي کنن و نياز به استفاده از T نيست .
در ادامه اون پياده سازي کلاس اومده . براي هر 3 تابع مي بينين که دوباره تعريف قالب رو آورديم . يعني اين جور نيست که يه بار بگيم T قالبه و براي همه توابع استفاده کنيم . بايد قبل از هر تابع ، قالب مورد استفاده در اونو مشخص کنيم .
يه مورد ديگه اي هم که هست اينه که مي بينين به جاي استفاده از نام کلاس قبل از عملگر دو تا دو نقطه ، از <Stack<T استفاده کرديم .
تابع main زياد مهم نيست . فقط به خط
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدتوجه کنين که يه Stack پنج عضوي از نوع double رو چجوري ايجاد کرديم .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنید
مرسی.
فقط اون تابعی اش رو نفهمیدم!
میشه 1 کم کاملتر توضیح بدید؟
ممنون
sin2x=2sinxcosx
21-08-2009, 19:48
ما به جاي اينکه از کلمات int و double و float و char تو ليست پارامترها و نوع داده برگشتي تابع استفاده کنيم از arrTemp استفاده کرديم . حالا هر نوع داده اي که ما بخوايم به تابع بفرستيم ميره تو نوع داده قالبي arrTemp قرار مي گيره و بعد sum رو که از نوع arrTemp تعريف کرديم دوباره برمي گردونيم .
چون ما اگه تو ليست پارامتر مون int مي نوشتيم و مي خواستيم براش عدد 12.32 بفرستيم مي گفت که متغير arr از نوع int تعريف شده و نمي تونه double ذخيره کنه .
sin2x=2sinxcosx
24-08-2009, 11:26
خوب حالا توابع بازگشتي .
به نظر من سخت ترين مبحث ++C همين توابع بازگشتي هستش . تو علم رياضيات هم هميشه بحث بازگشت پيچيده بود .
خود من هم تا حالا درست و حسابي اينو درک نکردم . ولي اگه يه برنامه اي رو بشه از طريق بازگشتي نوشت نسبت به مدل مشابه ساده خود بسيار بسيار حجم کد کمتري خواهد داشت . ولي هميشه بايد بين کارايي و زيبايي يکي انتخاب شود . چون برنامه هاي بازگشتي ظاهر مطلوبي ندارن . Trace کردنش براي هر کسي ساده نيست . مثلا براي من .
حالا شروع کنيم ببينيم چي ميشه . :20:
توابعي که خودشون رو در داخل بلاکشون احضار مي کنن توابع بازگشتي هستن . نه بابا !!! :31:
کلا اساس کار توابع بازگشتي اينه که اين گونه توابع معمولا دو قسمت دارن . يه قسمت که قسمت پايه ناميده ميشه رو مي دونن چجوري حل کنن . مثلا فرض کنين ما مي خوايم برنامه فاکتوريل رو از طريق توابع بازگشتي بنويسيم . اين تابع بازگشتي ما در حالت پايه مي دونه که فاکتوريل 1 و 0 ميشه 1 . بنابراين وقتي تو بلاکش با اين دو عدد مواجه ميشه بدون انجام هيچ کار اضافي عدد يک رو برمي گردونه . ولي وقتي با عددي مثل 2 روبرو شد ديگه نمي تونه اين قسمت رو حل کنه . بنابراين بايد تا جايي اين قسمتي رو که نمي تونه حل کنه رو ساده کنه تا برسه به حالت پايه . اين کار با فراخواني متوالي خودش انجام ميشه .
مثال برنامه فاکتوريل رو مي زنم و يه بار Trace اش مي کنم . من فقط تابع بازگشتي رو مي نويسم . تابع main رو نميارم . اينجا همون طور که مي دونين تابع main با يه آرگوماني تابع factorial رو احضار کرده . فرض کنين اين آرگومان 4 هست .
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدخط
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدرو نوشتن واقعا صحت و سلامتي کامل بدن رو مي طلبه . :31:
حالا اگه فرض کردين که آرگومان 4 هست اين 4 ميره تو number قرار مي گيره .
حالا شايد بپرسين long و unsigned چي هستن ؟
long يه نوع داده اي هست و unsigned هم مي گه که نمي تونيم تو number اعداد منفي قرار بديم . :13:
پرانتز بسته .
الان number ما برابر 4 هست . مياد ميگه آيا number <= 1 هست ؟ هست ؟ خير نيست . پس ميره سراغ else .
تو قسمت else تابع ما دوباره فراخواني ميشه . توسط خودش . با آرگومان number - 1 . يعني تو اين قسمت مي خواد
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدرو برگردونه . number ما که مشخصه 4 هست . ولي قسمت دوم مشخص نيست . پس 4 اينجا منتظر مي مونه و ميره دوباره تابع factorial رو با آرگومان number - 1 يعني 3 فراخواني مي کنه . اين بار هم number <= 1 نيست و مياد سراغ else . اين بار هم مي خواد
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدرو بر گردونه . الان number ما 3 هست . قبلا هم يه 4 داشتيم . پس اين بار هم 3 * 4 رو نگه مي داره و تابع factorial رو با آرگومان number -1 يعني 2 فراخواني مي کنه . باز هم number <= 1 نيست و مياد سراغ else . حالا 2 * 3 * 4 رو نگه مي داره و تابع رو با آرگومان 1 فراخواني مي کنه . اين بار ديگه مي رسه به حالت پايه . کار تابع تموم ميشه و نتيجه کار 2 * 3 * 4 يعني 24 هست . :41:
خودم هم نفهميدم چي گفتم .
ولي اگه سوالي هست مضايقه نکنين .:20:
توابعي که خودشون رو در داخل بلاکشون احضار مي کنن توابع بازگشتي هستن . نه بابا !!!
شما که همین کار رو کردی!
+
این کجاش سخت ترین بود؟!!×؟!؟×؟!؟!×
sin2x=2sinxcosx
24-08-2009, 12:47
شما که همین کار رو کردی!
+
این کجاش سخت ترین بود؟!!×؟!؟×؟!؟!×
در مورد جمله اولتون منظورتونو نفهميدم .
در مورد دومي هم يعني جدي راحت بود ؟ چون هم استاد هاي برنامه نويسي و هم استاد هاي رياضي ( ساختمان گسسته ) و هم خود ديتل هم به اين مسئله اعتراف کردن که بازگشت سخته .
منظورم همون چیزی ه که نقل قول کردم.
شما گفتی که توابعي که خودشون رو در داخل بلاکشون احضار مي کنن، بازگشتی نیستند.
ولی مثالی که زدی، دقیقاً خودش رو تو بلاک خودش احضار کرده و بلافاصله هم return کرده!
جدی کجاش سخت بود؟!؟ :دی
sin2x=2sinxcosx
24-08-2009, 13:51
شما گفتی که توابعي که خودشون رو در داخل بلاکشون احضار مي کنن، بازگشتی نیستند.
من کي همچين حرفي زدم ؟ :18:
احتمالا اين کلمه "نه بابا !!" شما رو دچار اشتباه کرده . اين رو يه جور ديگه براي خودتون تفسير کنين . قصدم شوخي بود .
جدی کجاش سخت بود؟!؟
کدوم قسمت ++C براتون سخته دوست عزيز ؟ :20:
احتمالا سختي اين قسمت زماني مشخص بشه که برنامه رو بدن بگن با تابع بازگشتي بنويس . شايد الان کد آماده رو مي بينين ميگين راحته .
به هر حال اگه شما به اين راحت بگين بقيه مطالب ++C از آب خوردن هم راحت تره .
CppBuilder2006
24-08-2009, 13:58
به نظر منم بازگشت راحته. من زیاد ازش استفاده میکنم. ولی برای خیلیا سخته. همون طور که برای خیلیا درس ریاضی سخت ترین درسه.
sin2x=2sinxcosx
31-08-2009, 11:24
سلام دوستان .................... :40:
بحث رو مي خوايم ادامه بديم ...
فايل ها
قبلا که برنامه مي نوشتيم ، داده ها رو تو متغيرها و آرايه ها به صورت موقتي ذخيره مي کرديم که با اتمام اجراي برنامه اين مقادير هم از بين مي رفتن . براي ذخيره دائمي اين داده ها ، اونا رو تو فايل ها ذخيره مي کنيم .
با توجه به اينکه منبع اصلي من براي اين قسمت يعني فايل ها ، فصل 17 کتاب ديتل هست ، و تو اون چند تا تعريف قبل از بحث فايل ها اومده ، من هم لازم مي دونم اونا رو ذکر کنم .
بيت : کوچکترين عنصر داده اي که کامپيوتر ها پشتيباني ميکنند .
بايت : هر هشت بيت يک بايت را تشکيل مي دهد .
کاراکتر : از ترکيب چند بيت ، کاراکتر تشکيل مي شود . ( نويسنده ( خودم ) : هر کاراکتر يا نوع داده اي char تو ++C ، يک بايت حافظه اشغال مي کنه . يعني هشت بيت . پس براي نمايش يک کاراکتر تو کامپيوتر به هشت تا صفر يا يک نياز هست که در نتيجه يک عدد هشت رقمي باينري تشکيل ميشه که معادل کد اسکي کاراکتر مورد نظر در مبناي 10 يا دسيمال هست . )
نکته ( نويسنده ) : البته کاراکترهاي Unicode دو بايت حافظه اشغال مي کنن که ما فعلا به اونا کاري نداريم .
فيلد : مجموعه اي از کاراکتر ها که معني و مفهوم داشته باشند . مثلا نام يک شخص .
رکورد : از ترکيب چند فيلد تشکيل مي شود . مثلا يک رکورد مي تونه شامل فيلد هاي زير باشه :
نام نام خانوادگي شماره شناسنامه محل تولد نام پدر نام پدربزرگ ...................
فايل : مجموعه اي از رکورد هاي مرتبط با هم
براي سهولت دسترسي به رکورد هاي خاص از فايل ، حداقل يک فيلد داخل هر رکورد به عنوان کليد رکورد در نظرگرفته ميشه . مثلا شماره شناسايي .
رکورد ها با چند روش مختلف در فايل ها سازمان دهي ميشن . نوع متداول اون ، فايل ترتيبي هست که رکوردها بر اساس کليد رکورد مرتب ميشن .
ممکنه شرکتي از چند فايل براي ذخيره داده هاش استفاده کنه . فايل حسابهاي دريافتي ، فايل حساب هاي پرداختي ، فايل انبارداري و . ... مجموعه اي از فايل هاي مرتبط با هم در يک بانک اطلاعاتي ذخيره مي شن . مجموعه برنامه هاي که براي ايجاد و مديريت بانک هاي اطلاعاتي طراحي ميشن سيستم مديريت بانک اطلاعاتي نام دارن .
++C هيچ ساختاري تو يه برنامه ايجاد نمي کنه . بنابراين مفهومي مثل رکورد در يک فايل ++C وجود نداره و برنامه نويس بايد خودش اين فايل ها رو سازمان بده .
خوب حالا .........
يه مثال مثل هميشه ميارم و توضيحات مربوطه :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبالا کاملا مشخصه که چرا اون هدرها رو include کرديم . iostream براي استفاده از نامهاي cerr , cin, cout, endl, ios . هدر fstream براي اسفاده از نام ofstream و cstdlib براي استفاده از نام exit . کاربرد هر کدومو خودتون خواهيد ديد .
اولين خط تابع مانند اينه که شيء outClientFile رو از کلاس ofstream نمونه سازي کرديم و به سازنده اش دو تا آرگومان فرستاديم که آرگومان محل ذخيره فايل در حافظه و نام فايل رو نشون ميده و آرگومان دوم نوع باز کردن فايل . که ios::out يعني اين که فايل براي نوشتن باز شه . در اين مورد بعدا توضيح مي دم . شرط بعدي نشون ميده که اگه به هر دليلي برنامه قادر به ايجاد فايل نبود برنامه فورا خاتمه پيدا کنه . بهتره که اينو هميشه داشته باشين . اگه outClientFile موجود نباشه مقدار false مي گيره که نقيض اون ميشه true و شرط اجرا ميشه .
حالا مي رسيم به قسمت :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدوقتي داخل شرط اورديم که while ( cin >> account يعني اينکه اگه عمليات ورودي موفقيت آميز هستش ، همون مقادير رو تو فايل ذخيره کن . اين جا براي خاتمه دادن به اجراي برنامه بايد کليد انتهاي فايل فشرده بشه که تو ويندوز ، CTRL + Z هست و بعد از اون کليد Enter بايد زده شه .
ادامه دارد .........
sin2x=2sinxcosx
05-09-2009, 00:29
سلام ...
قبلا گفتيم که وقتي از ofstream شيئي مي گيريم دو تا آرگومان بهش مي ديم که اونجا آرگومان دوم نوع باز کردن فايل رو نشون مي داد . گفتيم که ios::out براي نوشتن فايل هست . اگه فايل مربوطه به اين شکل باز شه ، محتويات قبليش حذف ميشه و فايل براي نوشتن مجدد آماده ميشه . اگه فايل از قبل تو اون محل مشخص شده وجود نداشته باشه ، يه فايل با اون نام ايجاد ميشه . اگه اين آرگومان دوم مشخص نشه ، به صورت پيش فرض ، فايل براي نوشتن باز ميشه . يعني ios::out انتخاب ميشه . بقيه حالت ها هم اينا هستن :
ios::app : داده ها رو تو ادامه فايل اضافه مي کنه . يعني در پايان فايل . همون جايي که ما قبلا با CTRL + Z مشخص کرديم .
ios::in : فايل رو براي خوندن باز مي کنه .
ios::trunc : اگه فايل از قبل موجود باشه محتويات فايل رو پاک مي کنه .
ios::binary : فايل رو براي خوندن و نوشتن به صورت باينري باز مي کنه .
راستي يه چيزي تو پست قبلي يادم رفته بودم بگم . آرگومان اول رو که به شيء outClientFile فرستاديم C:\\Client.dat بود . شايد بپرسين چرا از دو تا Backslash استفاده کرديم . براي اينکه براي چاپ يه علامت \ تو يه رشته يعني بين دو تا گيومه بايد از \\ استفاده کرد . زيرا خود \ يه escape sequence هست و بايد يه کاراکتر ديگه به دنبال اون بياد تا يه کاراکتر معني دار داشته باشن . مثلا شما از يه escape sequence به نام n\ استفاده مي کنين تا به خط بعدي برين .
گفتيم که مي تونيم به شيء مون آرگومان دوم رو نفرستيم . مي تونيم آرگومان اول رو هم نفرستيم و فقط يه شيء از ofstream ايجاد کنيم و بعدا فايلمون رو باز کنيم . يعني :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدبراي بستن فايل هم از دستور زير استفاده مي کنيم :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدتوصيه ميشه که وقتي با فايل ديگه کاري ندارين تو برنامه ، فايل رو ببندين .
قبلا يه فايل ايجاد کرديم و اطلاعاتي رو توش نوشتيم . حالا مي خوايم اطلاعات يه فايل رو بخونيم .
براي خواندن يه فايل ، يه شيء از ifstream ايجاد مي کنيم . مسير مورد نظر رو به اضافه نوع باز کردن فايل ( که ما اينجا براي خواندن مي خوايم يعني ios::in ) رو به عنوان آرگومان براش مي فرستيم . يعني :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدچون داده ها قبلا به صورت ترتيبي تو فايل نوشته شده بودن الان هم ميشه به ترتيب اونا رو خوند . مثلا سه تا متغير يکي از نوع int ، يکي آرايه اي از char و ديگري از نوع double تعريف کنين . همون طوري که موقع نوشتن اين کارو کردين . بعد از دستور زير براي انتقال داده ها به اين متغيرها استفاده کنين :
برای مشاهده محتوا ، لطفا وارد شوید یا ثبت نام کنیدفرض کرديم که اون سه تا متغيري که تعريف کردين اسمشون account و name و balance بودن . مي تونستين هر اسم ديگه اي تعريف کنين .
حالا مي تونين اين سه متغير رو توسط cout چاپ کنين تا ببينين که واقعا اين اطلاعات از فايل خونده شدن .
فکر کنم فايل ها تا همين جا کافي باشه . :46:
msojoudi
10-11-2009, 19:33
سلام من اومدم اون برنامه اولی رو بنویسم ولی ارور داد که نمی تونه فایل iostream رو پیدا کنه بعد من به option رفتم تا directories رو درست کنم اما دچار مشکل شدم اگه میشه یه توضیحی در این مورد بدید. ممنون
از چه ide استفاده میکنید؟؟؟
sin2x=2sinxcosx
10-11-2009, 21:20
به قول خانم پيشي دو صفر چهارده از چه IDE اي استفاده مي کنين ؟ احتمالا با تغيير اون به iostream.h جواب بگيرين .
چطوري ميشه تو++ C فارسي نوشت؟كي ميدونه؟
sin2x=2sinxcosx
12-11-2009, 22:13
چطوري ميشه تو++ C فارسي نوشت؟كي ميدونه؟
دقيقا متوجه نشدم . يعني چي فارسي نوشت ؟ کجاي برنامه ؟ خروجي فارسي بشه ؟
دقيقا متوجه نشدم . يعني چي فارسي نوشت ؟ کجاي برنامه ؟ خروجي فارسي بشه ؟
آره ديگه،يعني بتوني براش متغير فارسي تعريف كني ،كلاس فارسي،...بعد خروجي فارسي ام بده
مي دونم با برنامه سپند ميشه اينكارو كرد ولي مي خوام بدونم تو لينوكسم جواب ميده يا نه؟اگه نه چكار بايد كرد؟
vBulletin , Copyright ©2000-2025, Jelsoft Enterprises Ltd.