كيف يتم التحميل الذائد فى C++
سؤال : ما هو التحميل الزائد Overloading
اولا التحميل الزائد هو ترجمه حرفيه للمسمى Overloading ولكنى اميل لإستخدام تعريف الأستاذ تركى العسيرى و هو إعادة التعريف
تتم إعادة التعريف داخل الـ C++ بإستخدام أسم واحد لعدة دوال مع اختلاف نوع الـ Arguments و القيمة المعادة كالتالى
فالنفترض انك تريد معرفة القيمة المطلقه لرقم فستكتب دالتين احداهما تتعامل مع النوع int و الأخر float و كلاهما يأخذ الشكل
int abs(int); float abs(float);
و عند استخدامهم سيقوم المترجم بمعرفة اى الدالتين يستخدم بناءاً على القيمة المدخله منك فى الـ Argument.
و الله ولى التوفيق
تم تعديل هذه المشاركة بواسطة Game Expert في 8 يناير 2008 في 21:22
مدونتي: C++ Tips and Tricks
اخي ادريس..
اهلا وسهلا بك في المنتدى ..
التحميل الزائد او overloading من المواضيع الجميلة والصعبه في نفس الوقت ..
التحميل الزائد يوجد لشيئين في لغة سي++ .
الاول ان يكون مع الدوال .. فيسمى التحميل الزائد للدوال ..
والثاني مع المؤثرات .. فيسمى التحميل الزائد للمؤثرات ..
سأعطيك نظرة سريعه عن النوعين ..
الاول ..
لديك الدالة التاليه
void print(int x)
{
cout << x;
}لو جئنا الى الدالة الرئيسيه main وكتبنا التالي ..
void main()
{
int a;
cin >> a;
print(a)
}لنفترض ان المستخدم ادخل الرقم 10 للمرة الاولى.. فبالتأكيد الطبع على الشاشه سيكون 10 ...
ولكن لو ادخل المستخدم الرقم 11.16 اي رقم عشري يحتوي فارزه عشريه .. فسيطبع الرقم 11 فقط من دون الجزء الكسري .. لان الداله print التي قمنا ببرمجتها تأخذ معامل من نوع int .
ولكن لو اضفنا الداله التاليه ايضا مع البرنامج كله ..
void print(float x)
{
cout << x;
}وجاء المستخدم ليدخل ايضا في المرة الاولى 10 .. وفي المرة الثانية 11.16 ... فبالتأكيد سيطبع في المرة الاولى 10 وفي المرة الثانية 11.16 ..
لنحلل ما تم اعلاه ..
عندما تدخل الرقم 10 كمعامل للداله .. فان المترجم سيبحث اولا عن اسم هذه الداله فعندما يجد الاسم المطابق لها يبدأ في تنفيذها .. وبعدها يقارن المعامل الذي ارسل مع الداله من البرنامج الرئيسي main وينفذ ما تحتويه الداله ..
فعندما ادخل المستخدم الرقم 10 فان المترجم سوف يبحث عن الداله التي تاخذ المعامل من النوع الصحيح .. وينفذها .. وعندما ادخل المستخدم 11.16 فانه سيبحث عن دالة تاخذ المعامل من النوع العشري float لينفذها .. فبالتالي ايا كان الرقم المدخل صحيح ام عشري فانه سيطبع ..
لنأخذ مثال اخر ..
void add(int a)
{
cout << a++;
}
void add(int a,int b)
{
cout << a + b;
}
void main()
{
int x,y;
cin >> x >> y;
add(x);
cout << endl;
add(x,y);
}هذا البرنامج تم به تعريف دالتين .. الاولى تاخذ معاملا واحدا وتقوم فقط بالزياده عليه بواحد (++) اما الدالة الثانيه فتاخذ معاملين وتقوم بطباعة ناتج الجمع بينهما ..
نلاحظ في هذا البرنامج تحقق نفس ما ورد في المثال الاول .. وهو ان الدالتين لهما نفس الاسم ونفس نوع الارجاع ولكن الاختلاف في عدد المعاملات ..
فعند تنفيذ الداله add فان المترجم سيبحث عن الداله مع عدد ونوع المعاملات المرسله معها فاذا كان المعامل واحدا ينفذ الداله ذات المعامل الواحد اما اذا كانا معاملين فانه سينفذ الداله ذات المعاملين ...
لذلك نجد ان شرط التحميل الزائد للدوال هو ان تكون للداله نفس الاسم .. ولكن الاختلاف يكون في نوع الارجاع وفي عدد المعاملات وفي نوع تلك المعاملات .. فعندما نريد تنفيذ اي من هذه الدوال فان المترجم اول ما يبدأ به هو البحث عن اسم تلك الداله ثم بعدها يقارن نوعها مع نوع المرسله وكذلك يقارن عدد المعاملات مع عدد المعاملات المرسله وبعدها يقارن نوع تلك المعاملات ..
هذا بالنسبة للتحميل الزائد للدوال .. وهو النوع الاول ..
الثاني ..
المؤثرات هي كل رمز يستخدم في عملية حسابيه او منطقيه في لغة السي ++ .
مثال ذلك مؤثر الجمع + او الطرح - .. مؤثر المساواة = .. مؤثرات العلاقة < , > .. مؤثرات الطباعة << , >> .. المؤثرات المركبه =+ او = - .. وغيرها من المؤثرات الموجوده في اللغة ..
متى نقوم بالتحميل الزائد للمؤثرات .؟؟
نقوم بهذه العمليه فقط عندما نقوم ببرمجة كلاس جديد .. اي ان هذا الجزء هو من ضمن البرمجة الشيئية واحد اهم اركانها ..
لنأخذ مثال يوضح لنا العملية ..
لنفترض اننا برمجنا كلاس خاص بالقطط ..
class cat
{
int age;
public:
void getage(int a)
{
age = a;
}
};هذا كلاس بسيط (من الممكن ان يكون هناك خطأ برمجي او منطقي في الكود فهو للتوضيح وليس للتنفيذ) هذا الكلاس من خلاله ندخل عمر القطه فقط .. لنعرف كائن من نوع cat ..
cat foo;
الان foo اصبحت كائن من نوع cat ..
foo.getage(2);
ادخلنا بهذا السطر البرمجي عمر foo وهو 2 اي سنتين ...
لنعرف كائن اخر من نفس النوع ..
cat dezy;
الان القطه foo لها العمر سنتين .. القطه dezy لم ندخل لها عمرا بعد ..
ولكن شائت الاقدار ان تكون لها نفس الاعمار .. لذلك فانا اريد ان اجعل عمر foo مساويا لعمر dezy ..
dezy = foo;
انت تتوقع بان هذا الكود سيقوم بنقل العمر من foo الى dezy .. منطقيا صحيح .. ولكن برمجيا خطأ ولا يتم حتى نقوم باعادة تعريف = للكلاس الجديد الذي قمنا ببرمجته نحن الا وهو cat ..
انت سابقا كنت تستخدم الكود التالي ببساطه ..
int a =3 ,b; b = a;
هنا المؤثر الخاص بالمساواة سينقل القيمه او الرقم 3 من المتغير الاول الى الثاني .. قمنا باستخدام المؤثر = مباشرة لانه معرف مسبقا في المترجم على انه يقوم بهذا العمل ... ولكن بالنسبه لكلاس جديد قام المبرمج ببرمجته فان المترجم لا يعلم ان = فائدته نقل العمل من القطه الاولى الى القطه الثانيه .. لذلك يتوجب علينا اخباره بذلك .. وعملية اعادة التعريف هذه تتم بالشكل التالي ... طبعا داخل public..
cat& operator=(const cat& c1)
{
age = c1.age;
return *this;
}هنا تم تعريف الداله على انها من نوع cat وبعدها استخدمنا الكلمة المحجوزه operator لتخبر المترجم ان مابعدها هو الرمز الذي نريد اعادة تعريفه .. ثم داخل القوس تم تعريف كائن من نوع cat ليكون هو الجهة اليمنى من ال= ..
وبعدها تم نقل العمر من الكائن الذي عرفناه في اسم الداله الى العمر الحالي .. وبعدها نقوم بارجاع المؤشر this الخاص بالكائن الايسر ..
طبعا انا اعلم ان الموضوع متواضع ولكن هذا الذي استطيع ان اكتبه لاني لو اردت ان اتكلم عن التحميل الزائد للمؤثرات فلن اكمل للصبح ..
ولكن الحمدلله تعالى انا منذ مدة اكتب في كتاب خاص بالoverloading باللغة العربية وصلت الى مرحله جيده به لكي افيد به المبرمجين الجدد الذين لايعرفون هذا المبدأ الجميل والمفيد من البرمجة الكائنيه .. وكذلك لان الكتب العربيه لاتغطي هذا الجانب ..
ارجو ان يكون شرحي مفيدا لك ولجميع من قرأ الموضوع واي شئ انا حاضر في الخدمة ..
تحياتي العطرة ..
يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..
السلام عليكم و رحمة الله
----------------
الرد هذا بحول الله سيكون مزدوج الإجابة على سؤال الأخ ادريس و سؤال الأخت الدكتورة سارا. رايحة احول اجمع شتات معلوماتي عن هذه التقنية إن شاء الله
------------------------------
ليس لدي اكثر من الذي قدموه الأخ Game Expert و الأخ سنان وكان ردهم جزيل وجزاهم الله خير لكن ردي ان شاء الله رح يطل من نافذة أخرى على الموضوع.
------------------
أولا تقنية Overloading هي بالفعل إعادة تعريف للوظائف Functions وفي نفس الوقت فهي تقنية فعالة في مجال إعادة تعريف العمليات Operators Overloading داخل الأصناف classes. مسألة إعادة تعريف العمليات (المسألة الثانية) خارجة عن موضوع الرد هنا.
------
لمحة سريعة على إمضائة الإجراء Function Signature:
إمضائة الإجراء بالضبط مثل إمضائتنا نحن وهو عبارة عن توقيع يتميز به الإجراء عن الآخر و هذا التميز يكمن في عدد, نوع, و ترتيب المقتراحات الممررة إلى الإجراء Function Parameters list. نموذجياً, فإننا نقوم بتعين هذه الإمضائة(التوقيع) الخاص بالإجراء عند كتابة تصميم الإجراء المبدئي Function Prototypes. و هي في أول سطور البرنامج أو بالأحرى قبل استدعاء وإنشاء جسد الإجراء Function's Body {...}.
اوكي, الآن نقول أن إعادة تعريف الإجراء هو تقنية تسمح لأكثر من إجراء في البرنامج مقاسمة ومشاطرة اسم واحد فقط, و لكن يشترط في ذلك إختلاف الإمضائة The Signature. على سبيل المثال الإجراءات التالية تتمتع بهذه التقنية:
float funcName(); float funcName(float x, float y); int funcName(int x); void funcName(float x, float y, float z); void funcName(int x, int y);
ملاحظة: لا يهم نوع البيانات المسترجعة سواء تتشابه أو تختلف في هذه التقنية على الاطلاق. المهم أن تختلف في العدد, والترتيب, للمقترحات الممررة إلى الإجراء.
--------------------------
هذه التقنية The Overloading تنبض داخل ما يُعرف بـتعددية الأشكال The Polymorphism وهي من أبرز مميزات لغة ++C.
----------------------
الغموض The Ambiguity:
عند استعمال هذه التقنية فعلينا توخي الحذر مما يُعرف بـ الغموض The Ambiguity الذي قد ينتج عند استخدام تقنية Overloading للإجراءات. بمعنى آخر, هذه الغموض سيجعل المصرف The Compiler في حيرة وغموض عند نداء إجراءات معادة التعريف كالمثال التالي: طبعاً رايحة اكتب تعليق يوضح مكان الغموض بالشيفرة التالية:
//The following are two functions has been overloaded. float funcName(float i); double funcName( double i);
لاحظوا واحد يقوم باستقبال عدد float و الأخر يمرر Double. فعند نداء الإجراءات كالتالي تأملوا الغموض الذي سيحدث عن المصرف The compiler أثناء جمع البرنامج:
//The following is OK. It calls funcName(double i) cout << myfunc(10.1) << endl; //The following is ambiguous الغموض في التالي cout << myfunc(10);
نحن نعلم أن العدد 10 من الشيفرة بالأعلى قابلة للتحويل ضمنياً إلى النوع float او double فهنا سيكون الغموض على المصرف. و هناك أمثلة عدة بإمكانكم إجراء البحث او مراجعة مصدر آخر.
-----------------------
شو رايك اخت سارا ؟ لو كانت مثل الجافا أو لا؟ بلغة ++C المهم ترتيب البرمترات (الاقتراحات) يكون مختلف في حالة لو تساو في العدد.
طبعاً الإمضائة لازم تكون مميزة وعلى فكرة مو شرط نكتب اسم للمقترح المهم نوع المقترح مثل التالي:
float myFunc(float, int); int myFunc(int, int, int);
مع تمنياتي لكم بالتوفيق
تم تعديل هذه المشاركة بواسطة رغـــــــــد في 8 يناير 2008 في 22:48
[وسط]
♥ Countess ♥

♥
[/وسط]
Game Expert وسنان محمد صالح و رغــــد ...
ممتاز... شرح رائع منذ مدة لم نرَ هذه الردود المنظمة التي تشعرك انك تقرأ من كتاب سهل وواضح.
----| الموضوع ليس صعبا لكنه من اهم مميزات سي++ كما قالت الأخت رغد، وانصح السائل بقراءة فصل الـ Polymorphism في اي كتاب سي++ لأنه مهم جدا جدا للبرامج المعقدة
|----
أخت رغد ،شرحك ممتاز لكنني لا ارتاح لترجمة المصطلحات التي تستعملينها ..
كـ : المقترحات - هي ابعد ما يكون عن معنى اقتراح فهي تقدم للدالة كإجبار لا اقتراح..
الإجراء : الاجراء في باسكال يختلف عن الدالة، لكن في سي نقول دالة . أما الإجراء فهو الدالة التي لا ترجع قيَم، أو لنقل ترجع void. لكن عامة نقول دالة.
لأنها Function أما الاجراء فيترجم : Procedure .
أصناف : أفضل ترجمتها فئة (ج: فئات) - لكن لا اعترض على أصناف لأن فيها معنى. لكن ملاحظة.
---------
أرجو ان تفهم ملاحظاتي في إطار ملاحظات فقط، ولا تؤخذ بشكل شخصي ، فأنا فعلا معجب باللغة التي تستخدمينها وإلا ما كنت انتبهت لهذه الملاحظات..
حاولنا في الفريق العربي قبل 4 سنوات أو أكثر تأسيس قاموس للمطلحات بحيث نوحّد الترجمات، ولكن المشروع توقف قبل البداية.
تم تعديل هذه المشاركة بواسطة إسماعيل ابراهيم في 9 يناير 2008 في 10:55
اهلا بك اخ اسماعيل
---------------------
بالعكس انا مرنة جداً في تقبل الإنتقادات الإجابية و أنا عارفة بأن Procedure هو إجراء و Function هو وظيفة وكلمة دالة كلمة رياضية بحتة يا أخ اسماعيل. وهناك من يترجم كلمة Method بالتابع الوظيفي ولكن تقنياً هي سلوك للكائن لأن الإجراء لا يسمى بـ Method إلى إذا كان متعلق بكائن Object . أما بالنسبة لكلمة صنف class فهي من الاسم الجامع تصنيف The Classification من الفعل يصنف Classify. هذا بالإضافة إلى أنها أقرب برمجيا من فئة وهي Group.
بالإضافة إلى وصف لغة ++C بأنها تدعم البرمجة الإجرائية فإنهم كثيرا ما يقولون أنها Procedural Language وقل ما يقولون أنها Functional Language. نحنا بحقل لغة ++C نصف أي عمل إجرائي بكلمة إجراء
أما بالنسبة للإقتراحات Arguments فهي موجودة بأقوى الكتب (مي من راسي) وهي عمليا كأنك تقدم للإجراء اقتراحات يقوم بمعالجتها داخل الإجراء.
-------------
يعني حاولت اقدم الشيء الاكثر بريق و رسمية وخصوصاُ لغة ++C ذات نطاق واسع وهي اللي تفرض المصطلحات البرمجية وليست Pascal
----
تمنياتي لكم بالتوفيق
[وسط]
♥ Countess ♥

♥
[/وسط]
اخي اسماعيل واختي رغد كلامكما انتم الاثنين صحيح ومنطقي ..
ولكن حسب رايي الشخصي لو نستخدم الكلمة كما هي بالانكليزية افضل ..
وخير مثال موضعنا هذا .. كلمة التحميل الزائد كلمة غامضة بالعربيه .. فهي ترجمة حرفية لكلمة Over Loading ... وهناك بعض المراجع تترجم هذه الكلمة الى فرط التحميل .. ولكن كلا المعنينين يشيران الى ان هناك شئ فوق الطاقة .. ولكن هذا المعنى بعيد كل البعد عن ما هو مقصود ب over loading ..
ولكن اختي رغد اغلب المراجع تسمي Function بدالة .. وال Methode هي ايضا داله ولكن هي الدالة العضو في الكلاس ..
لذلك فانا من رأيي استخدام كل مصطلح باللغه الانكليزية افضل لكي يفهم كما هو ...
هذا رأيي والله اعلم ..
تحياتي العطرة..
يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..
موضوع الترجمة يحتاج جلسة خاصة، ما رأكم بفتحه في موضوع مستقل لأن هناك الكثير مما يقال ولا اريد افساد موضوع الأخ ادريس حسين ونخرجه عن مساره...
لا توجد اي مشكلة ..
رايك جميل اخ اسماعيل وهو سيقدم معلومات لنا وللاعضاء ..
لذلك فانا اؤيد هذه الفكرة ..
يَارَبُ إِن ضَاقَت قُلُوُب الْنَّاسٍ عَنْ مّافِي .. مِنْ خَيْرٍٍ فَعَفْوكَ لَا يَضِيْقْ ..
سنان محمد صالح كتب:لا توجد اي مشكلة ..رايك جميل اخ اسماعيل وهو سيقدم معلومات لنا وللاعضاء ..
لذلك فانا اؤيد هذه الفكرة ..
شكرا أخي لتأييدك :)
توكل على الله وافتح موضوعًا في المنتدى المناسب
وسنشارك بإذن الله...
تم تعديل هذه المشاركة بواسطة إسماعيل ابراهيم في 9 يناير 2008 في 18:47
مرحباً اختي سارا. الحمد لله طيبة يعافيك الله.
أولاً اختي سارا لا تحاولي تعملي مقارنة بينات Overloading و بين Overriding.
Overriding:
عبارة عن السماح للصنف الوارث Subclass من إعادة تعريف ميثود موجود بالأب الموروث Superclass.
Overloading:
عبارة عن وكما اخبرت سالفاً بأنها التقنية التي تسمح لأكثر من إجراء أو ميثود من مشاطرة (تقاسم) نفس الاسم و لكن بشرط اختلاف البرمترات.
و هي تتشابه في لغة ++C و هجينتها لغة Java. لكن في لغة ++C هناك استخدام لها بطريقة البرمجة الإجرائية أو البرمجة الشيئية ومع العلم بأن لغة Java لغة ذات برمجة شيئية تامة fully Object-oriented language. عشان كذا لا تحاولي تعملي خلط بين التقنيات
Hiding:
فكرة اخفاء وتغليف البيانات Encapsulation ليس لها ارتباط بموضوع overloading.
-----------------------
ان شاء الله تكون الفكرة وصلت.
والله وفقك اختي والجميع يا رب
[وسط]
♥ Countess ♥

♥
[/وسط]
نقاش ممتاز ،
اقتباسHiding:فكرة اخفاء وتغليف البيانات Encapsulation ليس لها ارتباط بموضوع overloading.
أظن انه المقصد هنا ليس حمايه البيانات أو تغليفها ، لكن المقصد هنا اخفاء الداله ،
مثلا لدينا كلاس أب اسمه BaseClass به دالتين print الأولى تأخذ وسيط والأخرى بدون .
الان عملنا اشتقاق من الـ BaseClass ل SubClass ،
في حال زودنا داله واحده print لهذا الكلاس تأخذ وسيط ، فاننا سوف نخفي الداله الأخرى التي لا تأخذ Hidding ، اي في البرنامج الرئيسي عند عمل Object من الـ SubClass لن نستطيع استدعاء الداله Print التي لا تأخذ وسيط ،
لذلك يجب علينا أن نعيد تعريف جميع الداول الoverloaded في الـ BaseClass .
أو أن نحدد اسم الكلاس بعدها :: ثم نكتب اسم الداله .
SubClass sc; sc.BaseClass :: print(); // ok sc.print(); // error , it's hidden from SubClass
هذا والله أعلم ،
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
عليكم السلام ورحمة الله
-------------
شكراً رومنسي على التوضيح.
---------------
اخت سارا انا فهمتك اكثر واكثر وعارفة انتي شو تريدي بالضبط. انتي ملمة بلغة Java وتحبي تشوفوا مقارنة بينها وبين لغة ++C. وانا حاسة انتي ملمة ايضاً باللغة الإنجليزية, انتقلي للرابط التالي عبارة عن مقالة فيها مقارنة ممتازة بين اللغتين:
وقبل ما تنتقلي خلي ببالك انك تقدري تتعلمي ++C ببساطة اكثر طالما انتي عندك لغة Java مسبقاً.
و هنا كل صغيرة و كبيرة تقريباً عن Overloading في لغة ++C.
بالطبع انصحك كمان بكتب ممتازة لو قررتي تنتقلي إلى لغة ++C:
The ++C Programming Language (By The ++C Creator himself Bjarne Stroustrup).
The ++C How To Program (Published by Prentice Hall by Deitel & Deitel)
The ++C from The GROUND UP (By Herbert Schildt).
حاولي تحصلي على طبعات حديثة من هذي الكتب
أو بإمكانك متابعة المحاضرات اللي يقدمها المشرف الأخ BjarenStudent في المنتدى هنا
اتمنى لك التوفيق اخت سارا
[وسط]
♥ Countess ♥

♥
[/وسط]
السلام عليكم ,,
يبدو أني وصلت متأخراً كالعادة :D
الصراحة الأخوة و الأخوات ما قصروا في شيء,,
ولكن هناك نقطين أود التعليق عليهما ظهرا خلال الموضوع ,,
الاقتراح المقدم بخصوص ترجمة المصطلحات,
الحقيقة أني أتمنى أن يكون لدينا مثل هذا الشيء في القسم, حتى لو على مستوى المصطلحات الأساسية فقط, لأني دائماً أقف محتاراً عندما أريد كتابة مصطلح باللغة العربية :(
إذا أردتم يمكننا فتح قسم خاص, أو أن نقوم بتثبيت موضوع فيه المصطلحات المترجمة, و بين الحين و الآخر نقوم بطرح مصطلح لمناقشة ترجمته و الوصول إلى أفضل ترجمة ثم إضافة المصطلح للموضوع المثبت ليصبح مرجعاً ثنائي اللغة,
أنا أنتظر منكم الرد, هل نفتح قسم أو يكون هناك موضوع مثبت ؟
دكتورة سارة,
أعتقد أني ما فهمت ما تقصدين,
أولاً هناك اختلاف جوهري في الـ polymorphism و الـ inheritance بين ++C و Java ,, ( كل ما لدي هو معلومات بسيطة لا أكثر أتمنى أن تفيد )
حسب معرفتي بالـ Java فإن كل الدوال التي يتم تعريفها في الفئة تعتبر virtual functions بشكل تلقائي, ما لم تستخدمي final على ما أعتقد :hmm:
في ++C, العكس هو الصحيح, أي أن الدوال ليست virtual ما لم نصرح بذلك,
دعنا نتكلم أولاً عندما تكون الدوال عادية أي ليست virtual, بالطبع في ++C عند وراثة أي فئة فإن الدوال يتم وراثتها, الفئة التي ورثت يمكن أن نعرف فيها دوال مطابقة للدوال في للفئة الأم و بالتالي تصبح الدوال overridden,
فإذا استدعينا الدالة من الفئة الأم فإن الدالة الموجودة في الفئة الأم هي التي ستنفذ, و إذا استدعيناها من الفئة التي اشتقت الأم فإن الدالة الموجود في الفئة المشتقة هي التي ستستدعى,
كل الدوال التي لم يحصل لها overriding فإنها تبقى على حالها في الفئة المشتقة.
الحالة الثانية هي عندما تكون الدوال معرفة في الفئة الأم على أنها virtual, بالطبع سنقوم بتعريف الدالة في الفئة المشتقة من جديد,
في ++C يمكن أن نعرف مؤشر من نوع الفئة الأم, بإمكان هذا المؤشر أن يشير إلى الفئة المشتقة, بالطبع لا يمكننا فعل العكس و هو إنشاء مؤشر من الفئة المشتقة يشير للفئة الأم,
عند استدعاء دالة virtual من المؤشر فإن برنامجنا سيضطر إلى اكتشاف نوع الكائن أولاً عن طريق الـ RTTI , ببساطة أكثر هل المؤشر يشير إلى الفئة الأم أو إلى فئة مشتقة منها, بعدها سيقوم بتحديد أي دالة يجب تنفيذها عن طريق الـ VTable! إما الدالة الموجودة في الفئة الأم أو الدالة الموجودة في الفئة المشتقة على حسب نوع الكائن الذي يشير إليه المؤشر الذي ذكرناه في بداية الأمر!
أخيراً أي دالة virtual لم يتم إعادة تعريفها في الفئة المشتقة فإن الدالة الموجودة في الفئة الأم هي التي ستستدعى بشكل طبيعي.
هذا بشكل بسيط, بالطبع خواص الـ polymorphism يمكن أن تصبح أكثر تعقيداً لو أن هناك وراثة على مستوى عدة طبقات, للأسف ليس لدي اطلاع على الأمر حالياً,
تحياتي ,,
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 10 يناير 2008 في 00:09
السلام عليكم ,,
دكتورة سارة,
أنا بدأت بذكر بعض الأمور عن الوراثة و تعدد الأشكال لكي نفهم الفرق بين معاملة ++C و كيف تختلف Java عنها في هذه الناحية,
بالنسبة لمعنى virtual, في ++C كل الدوال تعتبر دوال خاصة بالكائن الذي عرفت فيه إلا إذا عرفت على أنها virtual, في Java يمكنك مناداة دالة في الفئة الابن عن طريق الفئة الأم, و هذه الطريقة التي تتبعها Java بشكل تلقائي, أما في ++C فالأمر عائد للمبرمج و ذلك باستخدام الكلمة المحجوزة virtual,
على كل حال الموضوع كما تفضلتي يحتاج إلى تفصيل أكثر,, بإذن الله الأيام القادمة سيكون هناك المزيد من التركيز على هذه النقاط ,,
تحياتي ,,
السلام عليكم ,,
اقتباسانظر اخى كل الدوال فى الجافا تعتبر instance الا اذا وضعنا بجوارها كلمة static والتى اظنها عندكم فى السى بلس بلس virtualوفى هذة الحالة تبقى دالة واحدة لكل الobject الموجودة فى هذا الكلاس
في ++C كما في Java هناك Static members, و لكن الكلام حول virtual هو كلام عن الـ polymorphism و كيفية انشاء interfaces في ++C,
تحياتي ,,
هذا الموضوع مغلق.

