سؤال

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

هنا هو نسخة من الفئة التي يمر الدالة العضو:

class testMenu : public MenuScreen{
public:

bool draw;

MenuButton<testMenu> x;

testMenu():MenuScreen("testMenu"){
    x.SetButton(100,100,TEXT("buttonNormal.png"),TEXT("buttonHover.png"),TEXT("buttonPressed.png"),100,40,&this->test2);

    draw = false;
}

void test2(){
    draw = true;
}
};

وظيفة x.SetButton(...) الواردة في آخر الصف ، حيث "الكائن" هو قالب.

void SetButton(int xPos, int yPos, LPCWSTR normalFilePath, LPCWSTR hoverFilePath, LPCWSTR pressedFilePath, int Width, int Height, void (object::*ButtonFunc)()) {

    BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

    this->ButtonFunc = &ButtonFunc;
}

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

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

المحلول

استدعاء دالة عضو من المؤشر ، تحتاج إلى أمرين:مؤشر إلى كائن مؤشر إلى وظيفة.تحتاج كل في MenuButton::SetButton()

template <class object>
void MenuButton::SetButton(int xPos, int yPos, LPCWSTR normalFilePath,
        LPCWSTR hoverFilePath, LPCWSTR pressedFilePath,
        int Width, int Height, object *ButtonObj, void (object::*ButtonFunc)())
{
  BUTTON::SetButton(xPos, yPos, normalFilePath, hoverFilePath, pressedFilePath, Width, Height);

  this->ButtonObj = ButtonObj;
  this->ButtonFunc = ButtonFunc;
}

ثم يمكنك استدعاء الدالة باستخدام كل من المؤشرات:

((ButtonObj)->*(ButtonFunc))();

لا ننسى أن تمرير مؤشر إلى كائن إلى MenuButton::SetButton():

testMenu::testMenu()
  :MenuScreen("testMenu")
{
  x.SetButton(100,100,TEXT("buttonNormal.png"), TEXT("buttonHover.png"),
        TEXT("buttonPressed.png"), 100, 40, this, test2);
  draw = false;
}

نصائح أخرى

أود أن أوصي بشدة boost::bind و boost::function عن أي شيء مثل هذا.

انظر تمر استدعاء الدالة العضو (دفعة::ربط / دفعة::وظيفة؟)

أعرف أن هذا هو تماما الموضوع القديم.ولكن هناك طريقة أنيقة للتعامل مع هذا مع c++11

#include <functional>

تعلن المؤشر الدالة مثل هذا

typedef std::function<int(int,int) > Max;

تعلن الخاص بك وظيفة الخاص بك تمرير هذا الشيء في

void SetHandler(Max Handler);

افترض أنك تمر وظيفة طبيعية لذلك يمكنك استخدامه مثل العادية

SetHandler(&some function);

افترض أن لديك وظيفة عضو

class test{
public:
  int GetMax(int a, int b);
...
}

في التعليمات البرمجية الخاصة بك يمكنك تمرير ذلك باستخدام std::placeholders مثل هذا

test t;
Max Handler = std::bind(&test::GetMax,&t,std::placeholders::_1,std::placeholders::_2);
some object.SetHandler(Handler);

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

باستخدام المثال الخاص بك (لقد سميت 'test2' أسلوب 'buttonAction'):

class ButtonContract
{
  public:
    virtual void buttonAction();
}


class testMenu : public MenuScreen, public virtual ButtonContract
{
  public:
    bool draw;
    MenuButton<testMenu> x;

    testMenu():MenuScreen("testMenu")
    {
      x.SetButton(100,100,TEXT("buttonNormal.png"), 
              TEXT("buttonHover.png"), 
              TEXT("buttonPressed.png"), 
              100, 40, &this);
      draw = false;
    }

    //Implementation of the ButtonContract method!
    void buttonAction()
    {
      draw = true;
    }
};

في استقبال طريقة تخزين الإشارة إلى ButtonContract ، ثم عندما تريد إجراء الزر العمل فقط اتصل 'buttonAction' طريقة تخزين ButtonContract الكائن.

في الحالات النادرة التي يحدث أن تكون النامية مع Borland C++Builder و لا تمانع كتابة كود معين إلى أن بيئة التطوير (الذي هو رمز هذا لن يعمل مع C++ compilers) ، يمكنك استخدام __الإغلاق الكلمة.وجدت مقال صغير عن C++Builder الإغلاق.إنهم تهدف في المقام الأول لاستخدامها مع Borland VCL.

آخرون قالوا لك كيفية القيام بذلك بشكل صحيح.ولكن أنا مندهش لا أحد قال لك هذا الرمز هو في الواقع خطير:

this->ButtonFunc = &ButtonFunc;

منذ ButtonFunc هي المعلمة ، سوف تخرج من نطاق عندما ترجع الدالة.كنت تأخذ عنوانه.سوف تحصل على قيمة من نوع void (object::**ButtonFunc)() (مؤشر إلى مؤشر إلى وظيفة عضو) وإسناد ذلك إلى هذا->ButtonFunc.في الوقت الذي سيحاول استخدام هذا->ButtonFunc يمكنك محاولة الوصول إلى التخزين (الآن ليست موجودة بعد الآن) المحلية المعلمة و البرنامج الخاص بك سيكون على الأرجح الحادث.

أنا أتفق مع العميد الحل.ولكن يجب عليك تغيير الخط إلى

((ButtonObj)->*(ButtonFunc))();

منذ ButtonObj هو مؤشر إلى الكائن.

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