بخشی از پاورپوینت

اسلاید 1 :

مبحث:
توابع مجازي
Virtual Function
به نام حق

اسلاید 2 :

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

اسلاید 3 :

class Base
{
public:
int a,b;
Base()
{
a = 2;
b= 4;
}
};
class Derrived:public Base
{
public:
int m , n;
Derrived()
{
a = 5 , b = 7 , m = 13 , n = 15;
}
};

اسلاید 4 :

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

اسلاید 5 :

مروري بر ارث بري-ادامه
متغيرهاي از نوع كلاس مشتق ميتوانند به متغيرهاي از نوع كلاس پايه منتصب شوند و نه بالعكس.
Base b;
Derrived d;
b = d;
d = b;

اسلاید 6 :

مروري بر ارث بري-ادامه
اشاره گرهاي از نوع كلاس پايه ميتوانند به اشيا از نوع كلاس مشتق نيز اشاره كنند و نه بالعكس.
Base *bPtr;
Derrived d;
Derrived *dPtr;
bPtr = &d;
bPtr = new Base();
bPtr = new Derrived();
dPtr = new Base();

اسلاید 7 :

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

اسلاید 8 :

تعریف توابع مجازي:
مجازي يعني در ظاهر وجود دارد اما در باطن وجود ندارد.
هنگام استفاده از توابع مجازي، برنامه اي كه به نظر ميرسد تابعي از يك كلاس احضار ميكند ممكن است عملاً تابعي از كلاس ديگر را احضار كند

اسلاید 9 :

دلايل مطرح شدن توابع مجازي
1- آدرس متغيرهاي از نوع كلاس مشتق ميتوانند درون اشاره گرهاي از نوع كلاس پايه ذخيره شوند.
2- زماني كه يك تابع عضو كلاس از طريق اشاره گر فراخواني ميشود، با توجه به نوع اشاره گر تابع مربوطه از آن كلاس فراخواني ميشود.

اسلاید 10 :

class Base
{
public:
void Show()
{
cout<<“Base Show”< }
};
class Derived:public Base
{
public:
void Show()
{
cout<<“Derived Show”< }
};
void main()
{
Base varB;
Derived varD;
Base *ptr;
ptr = &varB;
ptr->Show();
ptr = &varD;
ptr->Show();
}
Base Show
Base Show

اسلاید 11 :

نتيجه تعريف تابع بصورت مجازي
در صورتي كه در مثال قبل تابع Show در كلاس پايه (Base) بصورت مجازي (virtual) تعريف شده باشد شاهد اين خواهيم بود كه در زمان اجرا تابع مربوط به كلاس مربوطه فراخواني ميشود.

اسلاید 12 :

class Base
{
public:
virtual void Show()
{
cout<<“Base Show”< }
};
class Derived:public Base
{
public:
void Show()
{
cout<<“Derived Show”< }
};
void main()
{
Base varB;
Derived varD;
Base *ptr;
ptr = &varB;
ptr->Show();
ptr = &varD;
ptr->Show();
}
Base Show
Derived Show

اسلاید 13 :

تقيد ديرهنگام
در مثال قبل هنگام كامپايل، كامپايلر نميداند محتواي ptr به چه كلاسي اشاره ميكند.
محتواي آن ميتواند آدرس شيئي از كلاس Base باشد ويا آدرس شيئي از كلاس Derived
هنگامي كه از توابع مجازي استفاده ميشود از آنجا كه آدرس تابع هنگام اجرا معلوم ميشود به آن تقيد ديرهنگام يا تقيد پويا ميگويند
توابعي كه از نوع مجازي نيستند هنگام كامپايل مشخص ميشود كه چه تابعي بايد فراخواني شود كه به آن تقيد زودهنگام يا تقيد استاتيك ميگويند

اسلاید 14 :

تقيد ديرهنگام
تقيد ديرهنگام نيازمند مقداري سربار است اما به ميزان زيادي قويتر و انعطاف پذيرتر ميباشد.

اسلاید 15 :

كلاس تجريدي و توابع مجازي محض
كلاس Shape را در مثال زير درنظر بگيريد
هيچ گاه ما يك شي از كلاس Shape ايجاد نميكنيم ولي تنها از آن براي تعيين ويژگيهاي مشترك تمامي اشيا استفاده ميشود.

اسلاید 16 :

كلاس تجريدي و توابع مجازي محض (ادامه.)
كلاس پايه اي را كه هيچ شيئي از روي آن ايجاد نميكنيم كلاس تجريدي مينامند
اگر يك تابع مجازي در كلاس را برابر با صفر قرار دهيم به آن تابع مجازي محض ميگويند.
يك كلاس بعنوان كلاس تجريدي است اگر و تنها اگر حداقل يك تابع مجازي محض داشته باشد.

اسلاید 17 :

class CShape
{
private:

public:
virtual void Draw(CDC *pdc)=0;
};
class CRectangle:public Shape
{
private:
int x1,y1,x2,y2;
public:
void Draw(CDC *pdc)
{
pdc->Rectangle(x1,y1,x2,y2);
}
};
class CCircle:public Shape
{
private:
int x,y,r;
public:
void Draw(CDC *pdc)
{
pdc->Circle(x,y,r);
}
};
void main()
{
CShape *ptr;
CRectangle rc;
CCircle ci;

ptr = &rc;
Ptr->Draw();
ptr = &ci;
Ptr->Draw();
}
تابع مجازي محض

اسلاید 18 :

مخربها و توابع مجازي
معمولاً مخربهاي كلاسها را بصورت مجازي تعريف ميكنيم
به تكه برنامه زير توجه كنيد.
در صورتي كه ما مخرب را در كلاس پايه بصورت مجازي تعريف نكرده باشيم هنگامي كه از دستور delete Ptr استفاده ميكنيم مخرب كلاس پايه فراخواني ميشود حال آنكه ميدانيم اين اشاره گر آدرس شيئي از نوع كلاس مشتق را حمل ميكرده است.
Base *Ptr;
Ptr = new Derived();

delete Ptr;

اسلاید 19 :

تمرين
كلاس پايه Shape را تعريف كنيد.
تابع Draw را بصورت تابع مجازي محض تعريف نماييد
تابع GetDataFromUser را نيز بصورت مجازي عضو كلاس Shape تعريف كنيد.
از كلاس Shape دو كلاس Rectangle و Circle را تعريف نماييد و دو تابع فوق را مجدد در اين كلاسها تعريف نماييد به گونه اي كه اطلاعات مورد نياز هر كلاس از كاربر گرفته شود و با توجه به نوع كلاس ترسيم مناسبي داشته باشيم.
درون برنامه يك اشاره گر از نوع Shape* تعريف نماييد.
هنگام اجرا از كاربر بخواهيد نوع شكل مورد نظرش را وارد كند و با توجه به نوع درخواستي يك شي از آن نوع ساخته شود و پس از گرفتن مشخصه هاي مود نيازش خودش را نمايش دهد.

در متن اصلی پاورپوینت به هم ریختگی وجود ندارد. برای مطالعه بیشتر پاورپوینت آن را خریداری کنید