نقل قول: Run-time Compile-time
چون برای استفاده از چندریختی (polymorphism)، از توابع مجازی (virtual functions) استفاده میشه و برای تشخیص استفادهٔ صحیح از این توابع، از RTTI (مخفف run-time type information) استفاده میشه و RTTI هم در زمان اجرا است.
نقل قول: Run-time Compile-time
از توضیحات شما متشکرم چون کاملا کاربردی و موثر بودن و من اگه اینا رو نمیدونستم به خوبی یادشون میگرفتم.اما سوال من یه چیز دیگه است.
میدونید که زمان کامپایل(که فقط یه بار اتفاق میفته)یعنی وقتی کد C++ به اسمبلی ترجمه میشه.زمان اجرا یعنی وقتی که کد به زبان اسمبلی یا زبان ماشین اجرا میشه.میخواستم بگم که این چیزهایی که بهشون میگن Run time polymorphism چه ویژگیهایی دارن که باعث میشه بهشون این اسم رو بدن؟در مورد compile time polymorphism چی؟
ممنون
نقل قول: Run-time Compile-time
compile time polymorphism (به اختصار در اینجا ctp مینویسم) با run time polymorphism (به اختصار در اینجا rtp مینویسم) متفاوت است از این لحاظ که ctp در زمان کامپایل از چندریختی بودن اطمینان حاصل میکند اما rtp در زمان اجرا از چندریختی بودن اطمینان حاصل میکند. توجه کنید که اگر این اطمینان وجود نداشته باشد، پس نمیتوان آنها را به کار بست.
ctp منظور برای همان سربارگذاری توابع (function overloading) است، البته templateها در زبان ++C هم به نوعی میتوانند مفهوم چندریختی را بر روی کلاسها اعمال کنند.
rtp هم که همان چندریختی در مفهوم شیئگرایی است و به این لحاظ rtp گفته میشود چون در زمان اجرا این اطمینان از نحوهٔ استفادهٔ آنها حاصل میشود (در زمان کامپایل نمیتوان به این اطمینان دست یافت).
نقل قول: Run-time Compile-time
نقل قول:
در زمان کامپایل نمیتوان به این اطمینان دست یافت
آها الان فهمیدم از اول باید چی میپرسیدم.چرا CTP در زمان کامپایل میشه ولی RTP نمیشه.اینو هیچ حا توضیح نداده بودن.البته درک میکنم که دیگه از زمینه آموزش C++ خارج میشه و شاید خیلی تخصصی بشه ولی حس میکنم با ندونستن این چیز مهمی رو از دست دادم و شی گرایی رو ناقص درک کردم.
ممنون
نقل قول: Run-time Compile-time
نقل قول:
نوشته شده توسط
Negative_Se7en
به این کد دقت کنید :
#include <iostream>
using namespace std;
struct A
{
virtual char* Foo (void) { return "Class A"; }
}*a;
struct B : A
{
virtual char* Foo (void) { return "Class B"; }
};
void Test (B* b)
{
cout<<"B* b is : "<<typeid(*b).name()<<endl;
b = dynamic_cast<B*>(b);
if(b){
cout<<"Succeed"<<endl;
}
else
cout<<"Failed"<<endl;
}
int main (void)
{
a = new A;
Test((B*)a);
getchar();
return 0;
}
شما نمیتونید مطما باشید که همیشه پارامتری که به تابع Test فرستاده میشود یک اشاره گر از یک B واقعی هست. یعنی ممکن است ریخت واقعی اشاره گری که به Test فرستاده میشود از یک نوع دیگه باشد.
برای همین شما باید این اطمینان رو با استفاده از dynamic_cast بدست بیارید.
دلیلش هم اینه که dynamic_cast در زمان اجرا (Run-Time) با استفاده از RTTI میتونه دقیقا نوع یک اشاره گر رو بررسی کنه و مانع از Cast های اشتباه بشه.
برای استفاده از dynamic_cast و شما باید قابلیت RTTI رو در کامایلرتون فعال کنید که به صورت پیش فرض در بیشتر کامپایلر ها فعال هست.
مثلا در کد بالا اشاره گر a به تابع Test فرستاده میشه ، و تابع Test با استفاده از dynamic_cast متوجه میشه که پارامتر فرستاده شده یک B واقعی نیست.
حالا اگر شما اشاره گر a رو به این صورت ;a = new B ایجاد کنی و به تابع تست ارسال کنی ، تابع تست متوجه میشه که این اشاره گر یک B واقعی است.
درکل بعضی از اشاره گرها در طول برنامه به ریخت های متفاوتی تبدیل میشوند (Poylymorphism) که شما با استفاده از dynamic_cast و typeid میتونید ریخت حال حاضر این اشاره گر ها رو در زمان Run-Time بررسی کنید.
خروجی این برنامه برای من این بود:
درسته؟ بنظرم مطابق انتظار نیست :متفکر:
نقل قول: Run-time Compile-time
هان فهمیدم! بنظرم شما باید کد رو جور دیگه ای مینوشتی. چون اول خودت cast معمولی به B کردی موقع پاس کردن به تابع Test که باعث میشه تابع مربوطه a رو واقعا از نوع B ببینه.
کد درستش بنظرم شبیه این میشه:
#include <iostream>
#include <typeinfo>
using namespace std;
struct A
{
virtual char* Foo (void) { return "Class A"; }
}*a;
struct B : A
{
virtual char* Foo (void) { return "Class B"; }
};
void Test (A* b)
{
cout<<"B* b is : "<<typeid(*b).name()<<endl;
b = dynamic_cast<B*>(b);
if(b){
cout<<"Succeed"<<endl;
}
else
cout<<"Failed"<<endl;
}
int main (void)
{
a = new A;
Test(a);
return 0;
}
نقل قول: Run-time Compile-time
یه سوال!
در 1A اون عدد 1 به چه معناست؟
نقل قول: Run-time Compile-time
نقل قول:
یه سوال!
در 1A اون عدد 1 به چه معناست؟
معنای خاصی نداره. :لبخند: در مورد تولید نام، کامپایلر تصمیم میگیرد.
نقل قول: Run-time Compile-time
جناب اشپیلن کد شما رو کامپایل کردم خروجیش شد این:
B* b is : 1A
Failed
خب این یه خرده عجیبه چون در کد اولیه ما هنگام فرستادن a به تابع اون رو به B* تبدیل میکنیم و میبینید که تبدیل با موفقیت انجام میشه و برنامه بدون مشکل اجرا میشه و خروجی میشه succeed.یعنی این تبدیل یه تبدیل مجازه.اما اینجا میبینیم که dynamic_cast تبدیل ما رو غیرمجاز میدونه.چرا؟
در ضمن سوال های من رو هم اگه میشه یکی جواب بدید(گفتم که اگه تاپیک منحرف شد(که داره میشه) من بی جواب نمونم)البته با منحرف شدنش مشکلی ندارم چون یاد گرفتن خوبه.
ممنون
نقل قول: Run-time Compile-time
نقل قول:
نوشته شده توسط
Shyan Javani
جناب اشپیلن کد شما رو کامپایل کردم خروجیش شد این:
B* b is : 1A
Failed
خب این یه خرده عجیبه چون در کد اولیه ما هنگام فرستادن a به تابع اون رو به B* تبدیل میکنیم و میبینید که تبدیل با موفقیت انجام میشه و برنامه بدون مشکل اجرا میشه و خروجی میشه succeed.یعنی این تبدیل یه تبدیل مجازه.اما اینجا میبینیم که dynamic_cast تبدیل ما رو غیرمجاز میدونه.چرا؟
خب فکر میکنم چون Cast معمولی خودش شعور نداره و هرچی شما بگی دربست گوش میکنه.
اگر بگی این B هست، کامپایلر همین فرض رو قبول میکنه و دیگه همه جا طرف رو B میبینه (حتی اگر سنخیتی با B نداشته باشه).
اما فرق dynamic_cast اینه که با استفاده از اطلاعاتی که در زمان اجرا راجع به ماهیت اشیاء در دسترس داره (RTTI) خودش تصمیم میگیره که تبدیل انجام شده معنا دار و مشروع هست یا نه.
نقل قول:
آها الان فهمیدم از اول باید چی میپرسیدم.چرا CTP در زمان کامپایل میشه ولی RTP نمیشه.اینو هیچ حا توضیح نداده بودن.البته درک میکنم که دیگه از زمینه آموزش C++ خارج میشه و شاید خیلی تخصصی بشه ولی حس میکنم با ندونستن این چیز مهمی رو از دست دادم و شی گرایی رو ناقص درک کردم.
خب فکر میکنم نیاز به نمونه کدهای عملی باشه.
ولی من نظر خودم رو توضیح میدم شاید گرفتی.
یکسری اشیاء رو چون ما در زمان اجرا و احتمالا بر اساس پارامترهای خارجی (مثل ورودی کاربر) ایجاد و دستکاری میکنیم، ماهیت اونها در زمان کامپایل از پیش مشخص نیست و ممکنه اصلا وجود نداشته باشن که کامپایلر بخواد تصمیمی درموردشون بگیره.
ضمنا حتی اگر کامپایلر تصمیمی برای بعضی اشیاء که در هنگام اجرا به نحوه های مختلفی تفسیر میشن یا تغییر میکنن بگیره، این تصمیمات ثابت خواهند بود و با توجه به پارامترهای زمان اجرا تغییر نمیکنن. بله فکر میکنم کلیتش همین باشه.
امیدوارم دوستان دیگه زحمتش رو بکشن و نمونه کدی چیزی بذارن.
نقل قول: Run-time Compile-time
واقعا ازتون ممنونم چون به جواب سوالی که از اول تاپیک رو به خاطرش زده بودم گرفتم.
اما اشپیلن فکرکنم تا حالا خطای زیر رو دیده باشی
Invalid conversion from 'char *' to 'char'
که نشان دهنده شعور تمام و کمال کست معمولیه
پس مسئله هنوز سر جاشه.
نقل قول:
خروجی این برنامه برای من این بود:
درسته؟ بنظرم مطابق انتظار نیست :متفکر:
در ضمن این کاملا مطابق انتظاره.فکر کنم یکی از معنی های polymorphism همین باشه که ما میتونیم از یه اشاره گر به شی پایه به متدهای ارث رسیده و از یه اشاره گر به شی مشتق به متدهای شی پایه دسترسی داشته باشیم.با توجه به این مطالب فکر کنم بشه گفت که این تبدیل مجازه و خروجی به دست اومده کاملا طبیعی
نقل قول: Run-time Compile-time
[QUOTE]
نقل قول:
نوشته شده توسط
Shyan Javani
واقعا ازتون ممنونم چون به جواب سوالی که از اول تاپیک رو به خاطرش زده بودم گرفتم.
اما اشپیلن فکرکنم تا حالا خطای زیر رو دیده باشی
Invalid conversion from 'char *' to 'char'
که نشان دهنده شعور تمام و کمال کست معمولیه
پس مسئله هنوز سر جاشه.
آخه همچین Cast هایی کاملا بی معنا و بدون کاربرد هست.
اون Cast های بی شعوری هم که گفتم درواقع چون میتونن درست و معنادار و دارای کاربرد باشن کامپایلر ازشون ایرادی نمیگیره (ولی درعین حال ممکنه برنامه نویس اشتباه کنه). این رو برنامه نویس باید تشخیص بده و کامپایلر بعهده نداره. یا نمیتونه در زمان اجرا صحت و معنادار بودنش رو تشخیص بده یا بخاطر افزایش سرعت و کاهش مصرف منابع از گردن خودش باز کرده.
مواردی مثل این که آوردی، عملا هیچ کاربردی در برنامه نویسی ندارن یا اگر داشته باشن یک روش کدنویسی بسیار بد هست که جایگزین خیلی بهتری داره و نیازی نیست اینکار رو بکنیم؛ بنابراین دیگه کامپایلر هم شعور میرسه و جلوش رو میگیره (کامپایلر شعورش میرسه، از برنامه نویس اونوقت بعیده اینکارا :لبخند:).
نقل قول: Run-time Compile-time
نقل قول:
کامپایلر شعورش میرسه، از برنامه نویس اونوقت بعیده اینکارا
خب من مبتدی هستم :خجالت:(فکز کنم در مواقعی رفتار مبتدی و بی شعور مثل هم بشه:متفکر:)