سؤال

في الكثير من C ++ API (القائم على com الربيع إلى الذهن) ذلك صنع شيء بالنسبة لك ، عادة ما يكون المؤشر إلى الكائن الذي تم إنشاؤه مطلوبًا كملف ** المؤشر (والوظيفة سوف تبنيها وبدءها من أجلك)

عادة ما ترى توقيعات مثل:

HRESULT createAnObject( int howbig, Object **objectYouWantMeToInitialize ) ;

- ولكن نادراً ما ترى الكائن الجديد يتم تمريره كقيمة إرجاع.

إلى جانب الأشخاص الذين يريدون رؤية رموز الخطأ ، ما سبب هذا؟ هل من الأفضل استخدام ** النمط بدلاً من المؤشر الذي تم إرجاعه لعمليات أبسط مثل:

wchar_t* getUnicode( const char* src ) ;

أم أنه من الأفضل كتابة هذا على النحو التالي:

void getUnicode( const char* src, wchar_t** dst ) ;

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

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

المحلول

"إلى جانب الرغبة في رموز الخطأ"؟

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

(بالمناسبة ، لا توجد قاعدة عالمية ** يعني أنه يجب عليك تحرير الكائن. هذا ليس هو الحال دائمًا ، وربما تكون فكرة سيئة استخدام شيء تعسفي لتذكيرك بالأشياء لتنظيفها.)

نصائح أخرى

سببين يتبادرا إلى ذهني.

الأولى هي رموز الخطأ في الواقع. بخلاف C ++ ، لا يحتوي C على استثناءات ، و COM هو C-API. كما تفضل العديد من المشاريع المستندة إلى C ++ عدم استخدام الاستثناءات لأسباب مختلفة. قد تكون هناك حالات ، حيث لا يمكن لقيمة الإرجاع الإشارة إلى أخطاء ، على سبيل المثال ، إذا كانت وظيفتك تقوم بإرجاع عدد صحيح ، فقد لا تكون هناك قيمة عدد صحيح ، يمكن أن تمثل رمز الخطأ. على الرغم من أن الأخطاء في الإشارة مع المؤشرات سهلة (NULL == ERROR) ، فإن بعض مصممي API يفضلون الإشارة إلى الأخطاء بطريقة متسقة على جميع الوظائف.

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

كائنات جديدة في وسيطات الوظائف التي تم تمريرها بواسطة ** أفضل. هذا يأخذني راحة للاستخدام في المستقبل للتغيير void ل bool على سبيل المثال لإرجاع نجاح وظيفة أو معلومات أخرى توفر الوظائف.

الإجابة في سطر واحد: هذا أفضل بكثير لرموز الخطأ الناتجة.

إلى جانب الأشخاص الذين يريدون رؤية رموز الخطأ ، ما سبب هذا؟

هناك بعض الأسباب لذلك. أحدهم يكتب واجهة قابلة للاستخدام في C (ترى هذا في Winapi و Windows COM).

التوافق المتخلف هو سبب آخر (أي تمت كتابة الواجهة على هذا النحو وكسرها الآن من شأنها أن تكسر التعليمات البرمجية الحالية).

سأذهب مع توافق C لمبدأ التصميم عند استخدام كود مثل هذا. إذا كنت تريد الكتابة في C ++ ، فستكتب

retval Myfunction(Result *& output);

بدلاً من

retval Myfunction(Result ** output);

أو حتى أفضل):

Result *Myfunction();

والحصول على وظيفة رمي استثناء على الخطأ.

لست متأكدًا من أنني أوافق على أن هذه هي أفضل طريقة للقيام بذلك ... قد يكون هذا أفضل:

Object * createAnObject(int howbig, HRESULT * optPlaceResultCodeHereIfNotNull = NULL);

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

في الواقع ، نظرًا لأنه C ++ ، يمكنك جعل الأمور أسهل ، باستخدام التحميل الزائد للوظيفة:

Object * createAnObject(int howbig);
Object * createAnObject(int howbig, HRESULT & returnResultCode);

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

عدم الإجابة على سؤالك ، ولكن تعليقًا لأن سؤالك قد أظهر بعض الأفكار التي لدي حول برمجة COM/DCOM باستخدام C ++.

كل هذه "المؤشر" و "المؤشر إلى المؤشر" ، وإدارة الذاكرة والعد المرجعية هي الأسباب التي تجعلني أخجل من القيام برمجة COM مع C ++. حتى مع وجود ATL في مكانه ، فإنني لا أحب ذلك لسبب بسيط هو أنه لا يبدو طبيعيًا بما فيه الكفاية. بعد قولي هذا ، فعلت بعض المشاريع باستخدام ATL.

في ذلك الوقت ، البديل هو استخدام VB. يبدو رمز VB أكثر طبيعية لبرمجة COM أو DCOM.

اليوم ، سأستخدم C#.

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