سؤال

ما هي بعض الاستخدامات العملية لـ "نمط القالب المتكرر الغريب"؟ال "الطبقة المحسوبة"المثال المعروض بشكل شائع ليس مثالاً مقنعًا بالنسبة لي.

هل كانت مفيدة؟

المحلول

محاكاة الربط الديناميكي.يعد تجنب تكلفة استدعاءات الوظائف الافتراضية مع الاحتفاظ ببعض المزايا الهرمية بمثابة فوز هائل للأنظمة الفرعية حيث يمكن القيام بذلك في المشروع الذي أعمل عليه حاليًا.

نصائح أخرى

كما أنها مفيدة بشكل خاص ل mixins (أعني بذلك الفئات التي ترث منها لتوفير الوظائف) والتي تحتاج هي نفسها إلى معرفة النوع الذي تعمل عليه (وبالتالي يجب أن تكون قوالب).

في فعالة C ++, يقدم سكوت مايرز كمثال قالب فئة NewHandlerSupport<T>.يحتوي هذا على طريقة ثابتة لتجاوز المعالج الجديد لفئة معينة (بنفس الطريقة التي يفعلها std::set_new_handler مع العامل الافتراضي new)، وعامل التشغيل new الذي يستخدم المعالج.من أجل توفير معالج لكل نوع، يحتاج الفصل الأصلي إلى معرفة النوع الذي يعمل عليه، لذلك يجب أن يكون قالبًا للفصل.معلمة القالب هي الفئة الفرعية.

لا يمكنك فعل ذلك بدون CRTP، نظرًا لأنك تحتاج إلى إنشاء قالب NewHandlerSupport بشكل منفصل، مع عضو بيانات ثابت منفصل لتخزين new_handler الحالي، لكل فئة تستخدمه.

من الواضح أن المثال بأكمله غير آمن للغاية، ولكنه يوضح هذه النقطة.

يقترح مايرز أن CRTP قد يُنظر إليه على أنه "افعل ذلك من أجلي".أود أن أقول أن هذا هو الحال بشكل عام بالنسبة لأي مزيج، ويتم تطبيق CRTP في الحالة التي تحتاج فيها إلى قالب مزيج بدلاً من مجرد فئة مزيج.

يصبح CRTP أقل فضولًا إذا اعتبرت أن نوع الفئة الفرعية التي تم تمريرها إلى الفئة الفائقة مطلوب فقط في وقت توسيع الطريقة.لذلك يتم تعريف جميع الأنواع.تحتاج فقط إلى النمط لاستيراد نوع الفئة الفرعية الرمزية إلى الفئة الفائقة، ولكنه مجرد إعلان أمامي - حيث أن جميع أنواع معلمات القالب الرسمية هي حسب التعريف - بقدر ما يتعلق الأمر بالفئة الفائقة.

نحن نستخدم، في شكل معدل إلى حد ما، تمرير الفئة الفرعية في بنية نوع السمات إلى الفئة الفائقة لتمكين الفئة الفائقة من إرجاع كائنات من النوع المشتق.التطبيق عبارة عن مكتبة لحساب التفاضل والتكامل الهندسي (النقاط، المتجهات، الخطوط، المربعات) حيث يتم تنفيذ جميع الوظائف العامة في الفئة الفائقة، وتحدد الفئة الفرعية فقط نوعًا معينًا:يرث CFltPoint من TGenPoint.كما أن CFltPoint كان موجودًا قبل TGenPoint، لذا كان التصنيف الفرعي طريقة طبيعية لإعادة هيكلة ذلك.

بشكل عام، يتم استخدامه للأنماط المشابهة متعددة الأشكال حيث لا تحتاج إلى أن تكون قادرًا على اختيار الفئة المشتقة في وقت التشغيل، فقط في وقت الترجمة.يمكن أن يؤدي ذلك إلى حفظ الحمل الزائد لاستدعاء الوظيفة الافتراضية في وقت التشغيل.

لاستخدام مكتبة العالم الحقيقي لـ CRTP، انظر إلى ATL وWTL (wtl.sf.net).يتم استخدامه على نطاق واسع هناك لتعدد الأشكال في وقت الترجمة.

إنه يبدو وكأنه نوع من C الماكرو:الاستفادة من أن الماكرو يتم تجميعه ليس في وقت التعريف، ولكن في وقت الاستخدام.

#define CALL_THE_RIGHT_FOO foo()

ملف:

static void foo() {
   // do file A thing
}
...
CALL_THE_RIGHT_FOO
...

ملف:

static void foo() {
   // do file B thing
}
...
CALL_THE_RIGHT_FOO
...

نمط استخدام القالب الذي تصفه يسمح لنا "باستدعاء الحق foo" في القالب الأصلي، وتأجيل تعريف ما هو الصحيح foo بالضبط حتى يتم إنشاء مثيل للقالب.باستثناء هذه الحالة، يكون التمييز بين ClassA::foo وClassB::foo بناءً على قيمة T في الأصل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top