PDA

View Full Version : سوال: چطوری می تونم واسه کلاسم رویداد درست کنم؟



hi.alir
یک شنبه 14 شهریور 1389, 17:33 عصر
من یه کلاس نوشتم واسه مدیریت خطا. اینطوریه که یه صف خطا داره بعد دونه دونه به اونا رسیدگی می کنه دیگه. مثل پنجره. فقط می خواستم بدونم واسه این کلاس چطوری باید بفهمم که الان تو صف خطا، خطایی وجود داره یا نه. منظورم مثل PeekMessage نیست، مثل GetMessage می گم. این تابع چطوری می فهمه که پیغامی وجود داره یا نه در حالی از CPU استفاده نمی کنه؟

hi.alir
جمعه 26 شهریور 1389, 21:58 عصر
شد 26 ام، من هنوز نفهمیدم چطوری event درست کنم.

PC2st
جمعه 26 شهریور 1389, 23:03 عصر
لطفاً بیشتر توضیح دهید، چه کلاسی و چطور برای مدیریت خطا نوشته‌اید، می‌خواهید برای چه چیزی event درست کنید؟ نوشتن یک شبه کد (کد کذابی تنها برای توضیح) می‌تواند سوال را واضح‌تر بیان کند.

hi.alir
شنبه 27 شهریور 1389, 05:44 صبح
بزارید یه طور دیگه بگم.
یه Button رو فرض کنید. مثلا دکمه OK تو یه پیغام خطا. وقتی که ما رو این دکمه کلیک می کنیم یه سری دستورات که حالا واسش تعریف شده انجام میشه. مثلا رنگش عوض بشه، یه کم بره تو و ....
حالا سوال من اینه که این Button از کجا می فهمه که روش کلیک شده تا یه واکنشی رو نشون بده؟

r00tkit
شنبه 27 شهریور 1389, 08:37 صبح
بزارید یه طور دیگه بگم.
یه Button رو فرض کنید. مثلا دکمه OK تو یه پیغام خطا. وقتی که ما رو این دکمه کلیک می کنیم یه سری دستورات که حالا واسش تعریف شده انجام میشه. مثلا رنگش عوض بشه، یه کم بره تو و ....
حالا سوال من اینه که این Button از کجا می فهمه که روش کلیک شده تا یه واکنشی رو نشون بده؟

از طرق ارسال windows message

با spy++ برید نگاه کنید :مشاهده می کنید که حتی برای حرکت موس هم یه message از طرف os به object مورد نظر( با handle مشخص) فرستاده می شه

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


protected override void WndProc

و با توجه به message مورد نظر event مطلوب رو درست کردم( یه نگاه به spy++ بکنید)

khorzu
شنبه 27 شهریور 1389, 09:20 صبح
اگه یه لیست از پوینتر هایی به فانکشن ها داشته باشیم که داخل حلقه پیغام به تناسب اون پوینتر ها صدا زده بشند می شه یه چیزی مثل رویداد های دات نت ساخت . برای چک کردن مثلا OnClik یک دکمه باید توی ساختار دکمه یه متود OnClick داشته باشیم و اونو توی لیستمون ثبت کنیم و وقتی رویداد اتفاق بیفته همه پوینتر های لیست OnClick صدا زده می شند .
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
البته فقط از متد های استاتیک یک کلاس می شه پوینتر گرفت که کنار اومدن با این هم کار پیچیده ای نیست .

hi.alir
شنبه 27 شهریور 1389, 09:28 صبح
حالا می تونم سوالم رو واضح تر بگم.
همونطوری که می دونید پیغام هایی که از طرف ویندوز به برنامه ارسال میشه تو یه لیستی ذخیره میشه که بهش میگن Message Queue. ما واسه اینکه بتونیم نسبت به پیغام های ویندوز واکنش نشون بدیم اول باید اون لیست رو چک کنیم تا ببینیم چه پیغام هایی به برنامه ارسال شده. واسه اینکار دو تابع وجود داره ( یا حداقل من دو تاش رو می دونم ). یکی که GetMessage هست و اون یکی هم PeekMessage.
بازم همونطور که می دونید PeekMessage بدون وقفه Message Queue رو چک میکنه. اما GetMessage از طریق PeekMessage پیغام رو دریافت می کنه و از طریق تابع WaitMessage صبر می کنه تا پیغام بعدی ارسال بشه و بعد دوباره با PeekMessage چک می کنه ( یا حداقل این چیزی هست که من می دونم ).
سوال اصلی من اینه که تابع WaitMessage چطوری اینکار رو انجام میده؟ از کجا می فهمه که ویندوز به برنامه پیغام فرستاده تا بعد با PeekMessage اون پیغام رو بگیرن؟


اگه یه لیست از پوینتر هایی به فانکشن ها داشته باشیم که داخل حلقه پیغام به تناسب اون پوینتر ها صدا زده بشند می شه یه چیزی مثل رویداد های دات نت ساخت . برای چک کردن مثلا OnClik یک دکمه باید توی ساختار دکمه یه متود OnClick داشته باشیم و اونو توی لیستمون ثبت کنیم و وقتی رویداد اتفاق بیفته همه پوینتر های لیست OnClick صدا زده می شند .
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~
البته فقط از متد های استاتیک یک کلاس می شه پوینتر گرفت که کنار اومدن با این هم کار پیچیده ای نیست
راستش سوال من دقیقا این نبود. سوال من سر صدا زدن OnClick هست. اینکه از کجا بفهمیم باید OnClick رو صدا زد. برنامه که نمیاد هر میلی ثانیه چک کنه ببینه موس رو دکمه هست یا نه. کیلک چپ موس فشرده شده یا نه تا این متد رو صدا بزنه.

khorzu
شنبه 27 شهریور 1389, 09:32 صبح
فکر نمی کنم راهی به جز حلقه بینهایت باشه . چون اگه این جوری بود که اصلا نیازی به صف نبود ... هر رویدادی اتفاق می افتاد ، winproc صدا زده می شد .

hi.alir
شنبه 27 شهریور 1389, 09:38 صبح
فکر نمی کنم راهی به جز حلقه بینهایت باشه . چون اگه این جوری بود که اصلا نیازی به صف نبود ... هر رویدادی اتفاق می افتاد ، winproc صدا زده می شد .
اگر چند تا پیغام همزمان ارسال میشد چی؟

khorzu
شنبه 27 شهریور 1389, 09:39 صبح
برنامه که نمیاد هر میلی ثانیه چک کنه ببینه موس رو دکمه هست یا نه. کیلک چپ موس فشرده شده یا نه تا این متد رو صدا بزنه. به نظرم دقیقا همین جوریه.



اگر چند تا پیغام همزمان ارسال میشد چی؟
باز هم نیاز به یک صف به ازای هر کلاس ثبت شده لازم نیست . یک صف توی kernel کافی بود .

hi.alir
شنبه 27 شهریور 1389, 09:44 صبح
به نظرم دقیقا همین جوریه. اگه اینجوری بود، یه جورایی CPU کم میاورد. و البته همیشه از تمام توان CPU داشت استفاده میشد. در حالی که اینطوری نیست. وقتی با برنامه های مثل Task Manager که نگاه می کنید، گاهی مصرف CPU تا 0% هم پایین میاد در حالی که رویداد ها سر جای خودشون هستند.


باز هم نیاز به یک صف به ازای هر کلاس ثبت شده لازم نیست . یک صف توی kernel کافی بود .
اینجوری لازم بود که تو اون صف معلوم بشه فلان پیغام واسه کدوم شی هست. ولی وقتی هر شی صف مخصوص به خودش رو داشته باشه خودش هم می دونه که کدوم صف واسه خودشه.

khorzu
شنبه 27 شهریور 1389, 09:51 صبح
اگه اینجوری بود، یه جورایی CPU کم میاورد. و البته همیشه از تمام توان CPU داشت استفاده میشد. در حالی که اینطوری نیست. وقتی با برنامه های مثل Task Manager که نگاه می کنید، گاهی مصرف CPU تا 0% هم پایین میاد در حالی که رویداد ها سر جای خودشون هستند. علت اینه ؛ استراحت :

while(true)
{
//do some things
Sleep(1);
}

برنامه که نمیاد هر میلی ثانیه چک کنه ببینه موس رو دکمه هست یا نه. کیلک چپ موس فشرده شده یا نه تا این متد رو صدا بزنه.البته حق با شماست می تونه این کارو OS انجام بده همون waitMessage. ولی نهایتا یکی باید انجام بده .

hi.alir
شنبه 27 شهریور 1389, 09:55 صبح
با وجود Sleep باز هم از CPU استفاده اضافی میشه.
وقتی که از WaitMessage استفاده میشه مقدار مصرفی CPU دقیقا برابر 0% هست تا زمانی که یه پیغام به برنامه ارسال بشه.
راستش تو #C یه چیزی به اسم delegate بود. ولی تو ++C هیچ چیزی واسه اینکار ندیدم. البته خب تو ++C خیلی چیزا ندیدم. :لبخند:

khorzu
شنبه 27 شهریور 1389, 11:48 صبح
راستش تو C#‎‎‎‎ یه چیزی به اسم delegate بود. ولی تو ++C هیچ چیزی واسه اینکار ندیدم.
#include <stdio.h>
void my_int_func(int x)
{
printf( "%d\n", x );
}
int main()
{
void (*foo)(int);
foo = &my_int_func;
/* call my_int_func (note that you do not need to write (*foo)(2) ) */
foo( 2 );
/* but if you want to, you may */
(*foo)( 2 );
return 0;
}


البته خب تو ++C خیلی چیزا ندیدم.
http://www.pic4ever.com/images/3ztzsjm.gif

hi.alir
شنبه 27 شهریور 1389, 12:19 عصر
راستش رو بخوای طرز کار با delegate رو بلد نیستم. اصلا نمی دونم به درد این کار می خوره یا نه.

PC2st
شنبه 27 شهریور 1389, 17:40 عصر
سوال اصلی من اینه که تابع WaitMessage چطوری اینکار رو انجام میده؟ از کجا می فهمه که ویندوز به برنامه پیغام فرستاده تا بعد با PeekMessage اون پیغام رو بگیرن؟من با Windows API آشنائی چندانی ندارم، اما همانطور که جناب khorzu گفت به احتمال زیاد این کار توسط یک حلقهٔ شرطی صورت می‌گیرد. چون تابع WaitMessage موجب تعلیق (معلق‌ماندن) دستورهای بعدی می‌شود که همین نشان‌دهندهٔ این است که تابع WaitMessage بصورت همگام (synchronous) کار می‌کند، یعنی همگام با جایی که از آنجا صدا (call) زده شده است، کار می‌کند. پس باعث تعلیق یا توقف آن دستورات می‌شود تا زمانیکه مقداری را برگشت دهد. همین توقف یا تعلیق بخاطر پردازش دستورات درون تابع WaitMessage است.


راستش تو C#‎‎‎‎‎‎ یه چیزی به اسم delegate بود. ولی تو ++C هیچ چیزی واسه اینکار ندیدم. البته خب تو ++C خیلی چیزا ندیدم. :لبخند:در سی++ خیلی چیزها دیدنی نیست، مثل property و event که به سادگی قابل پیاده‌سازی است اما به سبکی دیگر :لبخند::شیطان:
انواع delegate در زبان سی‌شارپ، حالت ایمن و منعطف‌تر انواع «اشاره‌گر به تابع» در زبان‌های C و سی++ است.
اگر درست به یاد داشته باشم، برای ایجاد یک رویداد (که صفی از delegateهاست) از کلمهٔ کلیدی event در زبان سی‌شارپ استفاده می‌شود.

در زبان سی++ نوع delegate نداریم، پس به جای آن می‌توان از «اشاره‌گر به تابع» استفاده کرد، اما در سی++ نوع «اشاره‌گر به تابع عضو (member function)» با نوع «اشاره‌گر به تابع غیر عضو (non-member function)» و «اشاره‌گر به تابع استاتیک عضو (static member function)» متفاوت است و نمی‌توان این دو نوع را به یکدیگر تبدیل نمود (اما در حالت غیر استاندارد و وابسته به پیاده‌سازی‌های کامپایلر می‌توان آنها را به یکدیگر تبدیل نمود)، به عبارت ساده‌تر، نوع اشاره‌گرهای زیر با یکدیگر ناسازگار (و غیر قابل تبدیل) است:


void (*f)()
void (*g)(int)
void (X::*h)()
پس استفادهٔ مستقیم از اشاره‌گرهای تابع ایدهٔ خوبی برای پیاده‌سازی رویدادها نیست. در مقابل، می‌توانید این اشاره‌گرها را درون یک کلاس جامع و مناسب (کلاسی مشابه delegate و حتی قدرتمندتر) پوشش دهید.

کتابخانهٔ boost کلاس‌هایی برای حل این مشکل (عدم ناسازگاری این اشاره‌گرها) دارد و می‌توانید از آنها استفاده کنید که ایده‌ای برای کلاس‌های std::function و std::bind در نسخهٔ بعدی استاندارد زبان سی++ هستند. این کلاس‌ها به شدت انعطاف‌پذیر هستند، بطوریکه حتی توابعی با لیست آرگومان‌های متفاوت را می‌توان در std::function (به عنوان یک کلاس منعطف به جای اشاره‌گر به تابع) قرار داد. این کلاس‌ها، ایدهٔ delegateها در سی‌شارپ را در سی++ انجام می‌دهند و تا جایی که می‌دانم اگر بهتر از آن نباشد، حداقل چیزی شبیه به آن است. هم اکنون کامپایلر من مدت زمان زیادی است که همراه با این دو کلاس عرضه می‌شود و می‌توانم از آنها در استاندارد C++‎‎‎‎‎0x استفاده کنم.

در حال حاضر کتابخانهٔ ‪libsigC++‎‎‎‎‎‬ روشی کارآمد را برای پیاده‌سازی eventها برای زبان سی++ انجام می‌دهد. کتابخانهٔ GTKmm نیز از آن استفاده می‌کند. روش کتابخانهٔ ‪libsigC++‎‎‎‎‎‬ توسط مفهوم سیگنال‌ها و اسلوت‌هاست، سیگنال را معادلی برای رویداد و همچنین اسلوت را تقریباً معادلی برای توابع پاسخگو یا delegateها در نظر بگیرید. چندین اسلوت به یک سیگنال متصل می‌شوند، به محض آنکه سیگنال منتشر شود، همهٔ اسلوت‌ها به ترتیب اجرا خواهند شد.

hi.alir
شنبه 27 شهریور 1389, 18:08 عصر
راستش این که از CPU استفاده نمیشه من رو گیج کرده. در واقع بیشتر از اینکه دنبال درست کردن event باشم، دنبال نحوه ی کارشم.
مشکل من اینه که اگر از یه حلقه استفاده کرده باشن باید از CPU استفاده بشه، ولی نمیشه.

khorzu
شنبه 27 شهریور 1389, 19:31 عصر
ممنون از PC2st (http://www.barnamenevis.org/forum/member.php?u=30917) ؛
مثل همیشه کامل و آکادمیک .

در سی++ نوع «اشاره‌گر به تابع عضو (member function)» با نوع «اشاره‌گر به تابع غیر عضو (non-member function)» و «اشاره‌گر به تابع استاتیک عضو (static member function)» متفاوت است و نمی‌توان این دو نوع را به یکدیگر تبدیل نمود ... نوع اشاره‌گرهای زیر با یکدیگر ناسازگار (و غیر قابل تبدیل) است.
- می شه توضیح بدید چرا؟ از نظر کامپایلر .
- می شه توضیح بدید اشاره گر به یک «تابع عضو (member function)» رو در زمان اجرا چطور می شه بدست آورد؟
- «کامپایلر من» ؟

PC2st
شنبه 27 شهریور 1389, 22:04 عصر
مشکل من اینه که اگر از یه حلقه استفاده کرده باشن باید از CPU استفاده بشه، ولی نمیشه. بله، یک حلقهٔ خالی همهٔ CPU را درگیر خود می‌کند... پس در تابع WaitMessage نیز باید به طریقی در پردازش تأخیر یا وقفه ایجاد شده باشد (و احتمالاً اینطور است). متاسفانه ویندوز open-source نیست، نمی‌توان در مورد جزئیات پیاده‌سازی آن مطلع شد، فقط می‌توان حدس و گمانه‌زنی کرد (از روی خروجی نتیجهٔ کار و رفتاری که تابع از خود بروز می‌دهد).


- می شه توضیح بدید چرا؟ از نظر کامپایلر .از نظر کامپایلر این کار شدنی است اما از نظر استاندارد زبان سی++ اینکار تعریف نشده است چون هر کامپایلر برای ارائه «اشاره‌گر به تابع عضو» روش خاص خود را بصورت درونی انجام می‌دهد، بطور مثال:

void (X::*f)(int);f یک متغیر از نوع «اشاره‌گر به تابع عضو» است که به هر تابعی از کلاس X که دارای یک آرگومان int و مقدار بازگشتی آن void باشد، می‌تواند اشاره کند (اشاره‌گر).
اما کامپایلر چطور آن را پیاده‌سازی می‌کند؟ استاندارد زبان سی++ هیچ قاعدهٔ خاصی برای اینکار مشخص نکرده است، پس هر کامپایلر می‌تواند هر آنطور که دوست دارد، آن را پیاده‌سازی کند (به خاطر افزایش کارآیی). در کامپایلری که من استفاده می‌کند و همچنین احتمالاً در سایر کامپایلرها، نوع متغیر f توسط کامپایلر بصورت زیر تفسیر و مورد استفاده قرار می‌گیرد (در درون و به دور از چشم برنامه‌نویس):

void (*f)(X*, int);پس همانطور که می‌بینید از دید کامپایلر، «اشاره‌گر به تابع عضو» همانند یک اشاره‌گر تابع غیر عضو است (البته نه به این سادگی، چون name mangling هنوز بر روی نام تابع اعمال نشده و همچنین سایر موارد ممکن)، اما طبق استاندارد زبان سی++ چنین چیزی به عنوان یک قاعده تأئید نشده و کامپایلر دیگری ممکن است از روش دیگری استفاده کند، مثلا:

void (*f)(int, X*);چونکه کامپایلر مختار است تا محل قرار گیری آرگومان *X را هر آنطور که دوست دارد در لیست آرگومان‌های تابع مشخص کند. همهٔ «توابع عضو کلاس X» بطور ضمنی دارای این پارامتر هستند (و این همان دلیلی است که توسط کلمهٔ کلیدی this به شیئ کلاس X دسترسی دارید).

جواب: بنابراین بخاطر این اختیاری که کامپایلر دارد و به خاطر اینکه محل قرارگیری آرگومان *X به نحوهٔ پیاده‌سازی زبان سی++ مربوط است و از حیطهٔ طراحی زبان سی++ خارج است، پس تبدیل «اشاره‌گر تابع عضو» به «اشاره‌گر تابع غیر عضو» در زبان سی++ تعریف نشده است. اما اگر کسی بخواهد می‌تواند این تبدیل را انجام دهد و کامپایلر نیز به او اخطار خواهد داد، برای انجام هر کاری، چندین و چند روش متفاوت وجود دارد، بهترین روش همان روشی است که استانداردترین است.


- می شه توضیح بدید اشاره گر به یک «تابع عضو (member function)» رو در زمان اجرا چطور می شه بدست آورد؟بطور مثال:


struct X { void xxx(int); };

...

void (X::*f)(int) = &X::xxx;
X x;
(x.*f)(0); //call x.xxx(0)

- «کامپایلر من» ؟ GNU Compiler Collection :لبخندساده:

hi.alir
یک شنبه 28 شهریور 1389, 07:39 صبح
الان که توضیح می دادید، یه سوالی واسه من پیش اومد. اشاره گر به یه تابع عضو دقیقا به کجا اشاره می کنه؟ منظورم اینه که مثلا ما 6 تا نمونه از یه کلاس داریم و یه اشاره گر به فلان تابع عضو اون کلاس. حالا اگر با اشاره گر اون تابع رو صدا بزنیم، چه اتفاقی می افته؟



بله، یک حلقهٔ خالی همهٔ CPU را درگیر خود می‌کند... پس در تابع WaitMessage نیز باید به طریقی در پردازش تأخیر یا وقفه ایجاد شده باشد (و احتمالاً اینطور است). متاسفانه ویندوز open-source نیست، نمی‌توان در مورد جزئیات پیاده‌سازی آن مطلع شد، فقط می‌توان حدس و گمانه‌زنی کرد (از روی خروجی نتیجهٔ کار و رفتاری که تابع از خود بروز می‌دهد).
یه روزی یکی از آشنایان داشت یه برنامه ای با ++C می نوشت، بعد یه خطا ی runtime داشت. جالب اینجاست که اون خطا تو کد های ماکروسافت رخ می داد :لبخند:. وقتی که خطا می داد مثل همیشه visual studio فایل کد ی که توش خطا رخ داده رو باز می کرد. دقیقا کد ها معلوم بود. یک فایل cpp کامل. تازه تغییرش هم دادیم تا بتونیم اون خطا رو برطرف کنیم. :لبخند:
راهی نیست که یه خطا تو WaitMessage رخ بده؟ :متفکر:

PC2st
یک شنبه 28 شهریور 1389, 13:06 عصر
با توجه به این مثال:


struct X
{
int u;
void xxx();
};


X x1;
X x2;
X x3;
x1.u = 1;
x1.xxx();
x2.u = 2;
x2.xxx();
x3.u = 3;
x3.xxx();
یک متغیر u به ازای هر نمونهٔ ساخته‌شده وجود دارد، پس کلاً سه متغیر u به ترتیب برای نمونه‌های x1 تا x3 ایجاد شده است.
اما فقط یک تابع xxx به ازای همهٔ نمونه‌های ساخته‌شده وجود دارد، پس کلاً یک تابع xxx برای همهٔ نمونه‌ها وجود دارد.

در نتیجه چگونه تابع xxx به ازای هر نمونه متمایز است؟ دلیل آن وجود یک آرگومان اضافه است که بطور ضمنی توسط کامپایلر ایجاد می‌شود، این آرگومان توسط کلمهٔ this مورد استفاده قرار می‌گیرد که نوع آن همان *X است و مکان قرارگیری آن در لیست آرگومان‌ها را در مطلب قبل نوشتم. بنابراین، به ازای همهٔ نمونهٔ ساخته‌شده از کلاس X، تابع xxx یکی است (برای همهٔ نمونه‌ها بطور مشترک استفاده می‌شود) و آن چیزی که تغییر می‌کند، مقدار آرگومان *X (و کلمهٔ کلیدی this) است.


الان که توضیح می دادید، یه سوالی واسه من پیش اومد. اشاره گر به یه تابع عضو دقیقا به کجا اشاره می کنه؟ منظورم اینه که مثلا ما 6 تا نمونه از یه کلاس داریم و یه اشاره گر به فلان تابع عضو اون کلاس. حالا اگر با اشاره گر اون تابع رو صدا بزنیم، چه اتفاقی می افته؟اشاره‌گر به تابع عضو به «خود تابع» اشاره می‌کند (چون تنها یک تابع به ازای همهٔ نمونه‌ها وجود دارد):



void (X::*f)() = &X::xxx;
در دستور مذکور، متغیر f به همان یک تابع xxxای اشاره می‌کند که بین همهٔ نمونه‌های ساخته‌شده از کلاس X مشترک است (بنابراین، آدرس آن برای همهٔ نمونه‌ها یکی است).

توسط این دستور:


(x1.*f)();
این اشاره‌گر بر روی متغیر x1 صدا زده می‌شود تا مقدار آرگومان *X در زمان اجرا مشخص شود، با مشخص شدن مقدار آرگومان *X در زمان اجرا تشخیص داده می‌شود که اشاره‌گر f باید بر روی چه نمونه‌ای (متغیری) تابع xxx را صدا بزند. در نتیجه تابع xxx (که f به آن اشاره‌می‌کند) با پارامتر x1 صدا زده می‌شود. یعنی دستور فوق ممکن است باعث اجرای تابع زیر گردد:

_X6251_xxx(x1);پارامتر x1 برای آرگومان *X (و کلمهٔ کلیدی this) است که بطور ضمنی توسط کامپایلر ایجاد شده بود. این نام ‪_X6251_xxx‬ از کجا آمد!؟ این نام توسط دستگاه پرس نام (name mangling) از کامپایلر ایجاد شده است، در اینصورت تابع xxx با یک تابع دیگر که عضو کلاس نیست، اشتباه گرفته نخواهد شد (اما در زبان C پرس نام صورت نمی‌گیرد، چون توابع فقط در یک حالت تعریف می‌شوند، اما در زبان سی++ توابع می‌توانند سربارگذاری شوند یا در فضاهای نامی متفاوتی وجود داشته باشند).


یه روزی یکی از آشنایان داشت یه برنامه ای با ++C می نوشت، بعد یه خطا ی runtime داشت. جالب اینجاست که اون خطا تو کد های ماکروسافت رخ می داد :لبخند:. وقتی که خطا می داد مثل همیشه visual studio فایل کد ی که توش خطا رخ داده رو باز می کرد. دقیقا کد ها معلوم بود. یک فایل cpp کامل. تازه تغییرش هم دادیم تا بتونیم اون خطا رو برطرف کنیم. :لبخند:
راهی نیست که یه خطا تو WaitMessage رخ بده؟ :متفکر:مورد جالب و عجیبی بوده! شاید فایل سرآیند آن بوده است. در مورد ایجاد خطا در WaitMessage امکان رخ دادن خطا در آن هست، که در اینصورت مقدار صفر را برخواهد گرداند و کد خطا را توسط تابع GetLastError می‌توانید بگیرید.

khorzu
یک شنبه 28 شهریور 1389, 14:01 عصر
struct X { void xxx(int); };
...
void (X::*f)(int) = &X::xxx;
X x;
(x.*f)(0); //call x.xxx(0)اما این که فایده نداره ... اطلاع دارید این چطور کار می کنه ؟

class AlienDetector
{
public:
AlienDetector();
void run();
sigc::signal<void> signal_detected;
};
class AlienAlerter : public sigc::trackable
{
public:
AlienAlerter(char const* servername);
void alert();
private:
// ...
};
int main()
{
AlienDetector mydetector;
AlienAlerter myalerter("localhost"); // added
mydetector.signal_detected.connect( sigc::mem_fun(myalerter, &AlienAlerter::alert) ); // changed
mydetector.run();
return 0;
}

راهی نیست که یه خطا تو WaitMessage رخ بده؟
http://www.pic4ever.com/images/126fs422682.gif

PC2st
یک شنبه 28 شهریور 1389, 16:10 عصر
اما این که فایده نداره ... اطلاع دارید این چطور کار می کنه ؟بله من هم گفته بودم که استفاده مستقیم از اشاره‌گر برای کار با eventها روش مناسبی نیست. در این مورد نیز از کتابخانهٔ ‪libsigC++‎‬ استفاده شده است، همان سیگنال و اسلوت که به جای رویداد و delegate، به کار می‌رود. در کدهای شما در این قسمت:


sigc::mem_fun(myalerter, &AlienAlerter::alert)همان اسلوتی است که ایجاد شده است (اشاره‌گر به تابع در پوشش این اسلوت قرار گرفته است).