سؤال

أحاول أن أفهم رمز المثال هذا بخصوص كائنات مساعد المتصفح.

في الداخل ، يقوم المؤلف بتنفيذ فئة واحدة تكشف واجهات متعددة (iObjectWithSite ، idispatch).

تقوم وظيفة QueryInterface بما يلي:

if(riid == IID_IUnknown) *ppv = static_cast<BHO*>(this);
else if(riid == IID_IObjectWithSite) *ppv = static_cast<IObjectWithSite*>(this);
else if (riid == IID_IDispatch) *ppv = static_cast<IDispatch*>(this);

لقد تعلمت أنه من وجهة نظر C ، فإن مؤشرات الواجهة هي مجرد مؤشرات إلى VTABLES. لذلك أعتبر أن C ++ قادر على إرجاع VTABLE من أي واجهة تم تنفيذها باستخدام Static_cast.

هل هذا يعني أن الفئة التي تم إنشاؤها بهذه الطريقة تحتوي على مجموعة من vTables في الذاكرة (iobjectwithsite ، idispatch ، إلخ)؟ ماذا يفعل C ++ مع تصادمات الاسم على الواجهات المختلفة (كل منها لديه واجهة QueryInterface ، AddRef ووظيفة الإصدار) ، هل يمكنني تنفيذ طرق مختلفة لكل منها؟

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

المحلول

نعم ، هناك طاولات V متعددة ، واحدة لكل واجهة موروثة. static_cast <> يعيدها. يتأكد المترجم من مشاركة الأساليب الشائعة في الواجهات الموروثة ، فإنه يملأ كل فتحة طاولة V مع مؤشر A إلى نفس الوظيفة. لذلك تحتاج فقط إلى تطبيق واحد من AddRef ، الإصدار ، QueryInterface. فقط ما تريد. لا شيء من هذا حادث.

هذه مشكلة فقط عندما يقوم Coclass بتنفيذ واجهات متعددة بنفس الطريقة التي تقوم بها لا تريد إعطاء نفس التنفيذ. طريقة icononnectionpoint :: Advise () هي مثال سيئة السمعة. أم أنه كان dadvise ()؟ لسوء الحظ ، لا أتذكر ما الذي اشتبه به وكيف تم حله ، فقد تم تغطيته بواسطة ATL Internals. كتاب جيد جدا بالمناسبة.

نصائح أخرى

في الميراث المتعدد ، يتم ترتيب vTables متعددة بالتسلسل مثل التنسيق التالي إذا تم إعطاؤه this مؤشر (الذي يشير إلى البايت الأول ، 01)

[01][02][03][04] [05][06][07][08] [09][10][11][12]
PTR of VTABLEA] [PTR of VTableB] [PTR of VTABLEC

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

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