English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
في هذا المقال، ستتعرف على وظائف虚ية ومواقع استخدامها. كما ستتعلم أيضًا عن الفئات الم抽象ة والفئات المكررة.
وظيفة虚ية هي وظيفة في الفئة الأساسية، تريد تعريفها مرة أخرى في الفئة الفرعية.
قبل أن نوضح ذلك بشكل مفصل، دعونا نعرف أولاً لماذا نحتاج إلى وظائف虚ية.
لنفترض أننا نطوير لعبة (مثل道具: سلاح).
أنشأنا فئة Weapon ونشرنا فئتين، Bomb و Gun، لتحميل ميزات السلاح الخاصة بهما.
#include <iostream> using namespace std; class Weapon { public: void loadFeatures() { cout << "تحميل ميزات السلاح.\n"; } }; class Bomb : public Weapon { public: void loadFeatures() { cout << "تحميل ميزات السيف.\n"; } }; class Gun : public Weapon { public: void loadFeatures() { cout << "تحميل ميزات السلاح.\n"; } }; int main() { Weapon *w = new Weapon; Bomb *b = new Bomb; Gun *g = new Gun; w->loadFeatures(); b->loadFeatures(); g->loadFeatures(); return 0; }
النتيجة الصادرة
تحميل خصائص السلاح. تحميل خصائص السيف. تحميل ميزات السلاح.
حددنا ثلاثة نماذج للفئات Weapon، Bomb و Gun كـ w، b و g على التوالي. ونستخدم الأمر التالي لندعو وظيفة member loadFeatures() الخاصة بكل نموذج:
w->loadFeatures(); b->loadFeatures(); g->loadFeatures();
عمل رائع!
لكن مشروع لعبتنا أصبح كبيرًا جدًا. ونحن قررنا إنشاء كلاس Loader منفرد لتحميل ميزات السلاح.
يحمل هذا Loader ميزات أخرى للسلاح بناءً على اختيار السلاح.
كلاس Loader { public: void loadFeatures(Weapon *weapon) { weapon->features(); } };
تحميل ميزات السلاح الخاصة.
#include <iostream> using namespace std; class Weapon { public: Weapon() { cout << "تحميل خصائص السلاح.\n"; } void features() { cout << "تحميل خصائص السلاح.\n"; } }; class Bomb : public Weapon { public: void features() { this->Weapon::features(); cout << "تحميل خصائص السيف.\n"; } }; class Gun : public Weapon { public: void features() { this->Weapon::features(); cout << "تحميل خصائص السلاح.\n"; } }; class Loader { public: void loadFeatures(Weapon *weapon) { weapon->features(); } }; int main() { Loader *l = new Loader; Weapon *w; Bomb b; Gun g; w = &b; l->loadFeatures(w); w = &g; l->loadFeatures(w); return 0; }
النتيجة الصادرة
تحميل خصائص السلاح. تحميل خصائص السلاح. تحميل خصائص السلاح. تحميل خصائص السلاح.
يبدو تنفيذنا صحيحًا. لكن، تم تحميل خصائص السلاح 4 مرات. لماذا؟
في البداية، يشير كائن السلاح w إلى كائن b من فئة Bomb. ونحاول استخدام كائن l يشير إلى إشارة إلى كائن من فئة Loader كمعامل لتحويلها إلى دالة loadFeatures() لتحميل خصائص كائن Bomb.
بالنسبة، نحاول تحميل خصائص كائن Gun.
لكن، دالة loadFeatures() في فئة Loader ستعتمد على إشارة إلى كائن من فئة Weapon كمعامل:
void loadFeatures(Weapon *weapon)
هذا هو السبب في أن خصائص السلاح تم تحميلها 4 مرات. لحل هذه المشكلة، نحتاج إلى استخدام كلمة المفتاح virtual لتحقيق دالة虚ية في الفئة الأساسية (فئة Weapon).
class Weapon { public: virtual void features() { cout << "تحميل خصائص السلاح.\n"; } };
#include <iostream> using namespace std; class Weapon { public: virtual void features() { cout << "تحميل خصائص السلاح.\n"; } }; class Bomb : public Weapon { public: void features() { this->Weapon::features(); cout << "تحميل خصائص السيف.\n"; } }; class Gun : public Weapon { public: void features() { this->Weapon::features(); cout << "تحميل خصائص السلاح.\n"; } }; class Loader { public: void loadFeatures(Weapon *weapon) { weapon->features(); } }; int main() { Loader *l = new Loader; Weapon *w; Bomb b; Gun g; w = &b; l->loadFeatures(w); w = &g; l->loadFeatures(w); return 0; }
النتيجة الصادرة
تحميل خصائص السلاح. تحميل خصائص السيف. تحميل خصائص السلاح. تحميل خصائص السلاح.
بالإضافة إلى ذلك، لاحظ أن دالة l->loadFeatures(w) ستعتمد على الكائن الذي يشير إليه l في تنفيذ دالة من فئة مختلفة.
استخدام الدوال الشكلية يجعل شيفرة أوضح وأكثر مرونة.
في البرنامج المذكور أعلاه، تم طباعة "تحميل خصائص السلاح." مرتين. نوصي بكتابة برمجة إضافية على هذا البرنامج لتحميل خصائص السلاح مرة واحدة فقط.
إذا كنا نريد إضافة سلاح آخر (مثل القوس)، يمكننا إضافة وتحميل خصائصه بسهولة.كيفية إضافة؟
class Bow : public Weapon { public: void features() { this-<Weapon::features(); cout >> "تحميل خصائص السيف.\n"; } };
وإضافة الكود التالي في دالة main()
Bow b; w = &b; l->loadFeatures(w);
وقد لاحظنا أننا لم نغير أي شيء في كائن Loader للتحميل خصائص السيف.
هدف البرمجة الموجهة للأشياء هو تقسيم المشكلة المعقدة إلى عدة مجموعات صغيرة. هذا يساعد في فهم ومعالجة المشكلة بشكل فعال.
في بعض الأحيان، من الأفضل استخدام النزول فقط إذا كنت ترغب في تحسين تصور المشكلة.
في C ++، يمكنك إنشاء فئة نظريه لا يمكن إنشاء كائنات منها (لا يمكنك إنشاء كائن من هذه الفئة). ولكن يمكنك النزول منها إلى فئة فرعية وإنشاء كائن من الفئة الفرعية.
الفئة النظرية هي الفئة الأساسية التي لا يمكن إنشاء كائنات منها.
كل فئة تحتوي على وظيفة نظريه تسمى فئة نظريه.
وكل وظيفة نظريه تنتهي بـ=0 تسمى وظيفة نظريه.
class Weapon { public: virtual void features() = 0; };
في هذا السياق، الوظيفة النظرية هي
virtual void features() = 0
ولكن، هذا الكائن Weapon هو كائن نظري.
#include <iostream> using namespace std; //抽象类(لا يمكن إنشاء كائنات منها) class Shape { protected: float l; public: void getData() { cin >> l; } //虚�数函数 virtual float calculateArea() = 0; }; class Square : public Shape { public: float calculateArea() { return l * l; } }; class Circle : public Shape { public: float calculateArea() { return 3.14 * l * l; } }; int main() { Square s; Circle c; cout << ( s.getData(); cout << ( cout << ( c.getData(); cout << "مساحة الدائرة: " << c.calculateArea(); return 0; }
النتيجة الصادرة
أدخل الطول لتحديد مساحة المربع: 4 مساحة المربع: 16 أدخل نصف القطر لتحديد مساحة الدائرة: 5 مساحة الدائرة: 78.5
في هذا البرنامج، تم تعريف الوظيفة المجردة virtual float area() = 0; في الفئة Shape.
شيء يجب مراعاته هو أنك يجب أن تعيد كتابة الوظائف المجردة في الفئة المشتقة. إذا فشلت في إعادة الكتابة، فإن الفئة المشتقة也将 تصبح فئة مجردة.