c - موقع - voting




تمرير المزيد من المعلمات في مؤشرات وظيفة C (6)

لنفترض أنني أقوم بإنشاء برنامج الشطرنج. لدي وظيفة

void foreachMove( void (*action)(chess_move*), chess_game* game); 

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

chess_move getNextMove(chess_game* game, int depth){
  //for each valid move, determine how good the move is
  foreachMove(moveHandler, game);
}

void moveHandler(chess_move* move){
  //uh oh, now I need the variables "game" and "depth" from the above function
}

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

كيف يمكنني تمرير معلمات إضافية إلى وظيفة أن أدعو من خلال مؤشر؟


+1 إلى أنطونيو. تحتاج إلى تغيير إعلان مؤشر الدالة الخاص بك لقبول معلمات إضافية.

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

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


آه، إذا كان C فقط يدعم الإغلاق ...

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

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

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

http://publications.gbdirect.co.uk/c_book/chapter9/stdarg.html

فقط لمعلوماتك، حول رمز المثال في الرابط: بعض الأماكن لديهم "ن يجادل" والآخرين هو "n_args" مع تسطير السفلية. يجب أن يكون لديهم كل تسطير السفلية. اعتقدت أن بناء الجملة بدا مضحك قليلا حتى أدركت أنها أسقطت تسطير السفلية في بعض الأماكن.


إذا كنت ترغب في استخدام بعض C ++، يمكنك استخدام "كائن دالة":

struct MoveHandler {
    chess_game *game;
    int depth;

    MoveHandler(chess_game *g, int d): game(g), depth(d) {}

    void operator () (chess_move*) {
         // now you can use the game and the depth
    }
};

وتحويل foreachMove الخاص بك إلى نموذج:

template <typename T>
void foreachMove(T action, chess_game* game);

ويمكنك أن تسميها مثل هذا:

chess_move getNextMove(chess_game* game, int depth){
    //for each valid move, determine how good the move is
    foreachMove(MoveHandler(game, depth), game);
}

لكنها لن تعطل استخدامات أخرى من MoveHandler .


وهناك خيار آخر هو تعديل هيكل chess_move بدلا من نموذج وظيفة. ومن المفترض أن يتم تعريف الهيكل في مكان واحد فقط بالفعل. إضافة أعضاء إلى هيكل، وملء الهيكل مع البيانات المناسبة قبل أي مكالمة التي يستخدمها.


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

ما الذي يجري في هذه الوظيفة؟ هل لديك شرط أن يقول،

if (depth > -1) //some default
  {
  //do something
  }

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

هل تشير إلى أن الوظيفة تتطلب أحيانا "لعبة" و "عمق"؟ حسنا، ربما جعل وظيفتين واستخدام كل واحد عندما كنت في حاجة إليها.

ولكن، وجود هيكل كما الحجة هو على الارجح أسهل شيء.





pointers