سؤال

كما أفهم ، فإن المصطلح PIMPL موجود فقط لأن C ++ يفرض عليك وضع جميع أعضاء الفصل الخاص في الرأس. إذا كان الرأس سيحتوي فقط على الواجهة العامة ، من الناحية النظرية ، فإن أي تغيير في تنفيذ الفصل لن يستلزم إعادة ترجمة لبقية البرنامج.

ما أريد معرفته هو سبب عدم تصميم C ++ للسماح بمثل هذه الراحة. لماذا يطلب على الإطلاق عرض الأجزاء الخاصة من الفصل علانية في الرأس (لا يقصد التورية)؟

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

المحلول

هذا له علاقة بحجم الكائن. يتم استخدام ملف H ، من بين أشياء أخرى ، لتحديد حجم الكائن. إذا لم يتم إعطاء الأعضاء الخاصين فيه ، فلن تعرف حجم كائن جديد.

ومع ذلك ، يمكنك محاكاة سلوكك المطلوب بما يلي:

class MyClass
{
public:
   // public stuff

private:
#include "MyClassPrivate.h"
};

هذا لا يفرض السلوك ، لكنه يخرج الأشياء الخاصة من ملف .h. على الجانب السلبي ، يضيف هذا ملفًا آخر للحفاظ عليه. أيضًا ، في Visual Studio ، لا يعمل Intellisense مع الأعضاء الخاصين - قد يكون هذا زائد أو ناقصًا.

نصائح أخرى

أعتقد أن هناك ارتباك هنا. المشكلة ليست عن الرؤوس. لا تفعل الرؤوس أي شيء (فهي مجرد طرق لتضمين أجزاء مشتركة من نص المصدر بين عدة ملفات رمز المصدر).

المشكلة ، بقدر ما يوجد واحد ، هي أن الإعلانات الطبقية في C ++ يجب أن تحدد كل شيء ، عام وخاص ، أن مثيلًا يحتاج إلى العمل. (وينطبق الشيء نفسه على Java ، ولكن الطريقة التي تشير بها إلى أعمال الفئات المبللة خارجيًا تجعل استخدام أي شيء مثل الرؤوس المشتركة غير ضروري.)

في طبيعة التقنيات المشتركة الموجهة للكائنات (وليس فقط C ++ واحدة) ، يحتاج شخص ما إلى معرفة الفئة الخرسانية التي يتم استخدامها وكيفية استخدام مُنشئها لتقديم تطبيق ، حتى لو كنت تستخدم الأجزاء العامة فقط. الجهاز في (3 ، أدناه) يخفيه. تفصل الممارسة في (1 ، أدناه) المخاوف ، سواء كنت تفعل (3) أم لا.

  1. استخدم الفئات المجردة التي تحدد فقط الأجزاء العامة ، وخاصة الأساليب ، واترك فئة التنفيذ ترث من تلك الفئة التجريدية. لذلك ، باستخدام الاتفاقية المعتادة للرؤوس ، هناك ملخص. هناك أيضًا تطبيق. HPP يعلن الفئة الموروثة والتي يتم نقلها فقط إلى الوحدات النمطية التي تنفذ طرق التنفيذ. سوف يقوم ملف Applementation.HPP #بملعب "Abstract.hpp" للاستخدام في إعلان الفصل الذي يصدره ، بحيث تكون هناك نقطة صيانة واحدة لإعلان الواجهة المستخرفة.

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

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

تمت المهمة.

أوه ، يجب أن تعمل إعادة التجميع وإعادة الإصلاح بالطريقة التي تريدها ، وتجنب إعادة توحيد الوحدات النمطية عندما يتغير التنفيذ فقط (نظرًا لأن وحدة الاتصال لم تعد تقوم بأي تخصيصات تخزين للتطبيقات).

أنت تتجاهل جميعًا نقطة السؤال -

لماذا يجب على المطور كتابة رمز PIMPL؟

بالنسبة لي ، فإن أفضل إجابة يمكنني التوصل إليها هي أنه ليس لدينا طريقة جيدة للتعبير عن رمز C ++ الذي يتيح لك العمل عليه. على سبيل المثال ، تجميع الوقت (أو المعالج المسبق ، أو أيًا كان) التفكير أو رمز DOM.

يحتاج C ++ بشكل سيء إلى واحد أو كلاهما ليكون متاحًا للمطور للقيام برمجة ميتا.

ثم يمكنك كتابة شيء مثل هذا في MyClass العام الخاص بك:

#pragma pimpl(MyClass_private.hpp)

ثم اكتب مولد غلاف تافهة تمامًا.

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

اللغة معقدة بالفعل إلى حد ما ؛ أعتقد أن آلية لتقسيم تعريفات البيانات المنظمة عبر الكود ستكون قليلاً من الكارثة.

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

قد يكون لأن حجم الفصل مطلوب عند تمرير مثيله حسب القيم ، وتجميعه في فئات أخرى ، وما إلى ذلك؟

إذا لم يدعم C ++ دلالات القيمة ، فسيكون ذلك جيدًا ، لكنه كذلك.

نعم ، لكن ...

تحتاج إلى قراءة كتاب Stroustrup "تصميم وتطور C ++". كان من الممكن أن يمنع امتصاص C ++.

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