문제

클래스 내의 멤버 함수를 멤버 함수 클래스 포인터를 취하는 함수로 전달하려고합니다. 내가 가진 문제는이 포인터를 사용하여 클래스 내에서 올바르게 수행하는 방법을 잘 모르겠다는 것입니다. 누구든지 제안이 있습니까?

회원 기능을 전달하는 클래스 사본은 다음과 같습니다.

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 이런 식으로.

보다 멤버 함수를 통과하고 호출하십시오 (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'메소드를 호출하십시오.

드문 경우 Borland C ++ Builder와 함께 개발 중이며 해당 개발 환경 (즉, 다른 C ++ 컴파일러와 작동하지 않는 코드)에 맞는 코드를 작성하는 것이 마음에 들지 않습니다. __closure 키워드를 사용할 수 있습니다. . 나는 a를 찾았다 C ++ 빌더 폐쇄에 관한 작은 기사. 그들은 주로 Borland VCl과 함께 사용하기위한 것입니다.

다른 사람들은 당신에게 그것을 올바르게하는 방법을 당신에게 말했습니다. 하지만 아무도이 코드가 실제로 위험하다고 말하지 않았다는 것에 놀랐습니다.

this->ButtonFunc = &ButtonFunc;

ButtonFunc은 매개 변수이므로 함수가 반환 될 때 범위를 벗어납니다. 당신은 주소를 취하고 있습니다. 당신은 유형의 값을 얻게됩니다 void (object::**ButtonFunc)() (멤버 함수에 대한 포인터에 대한 포인터) 그리고이-> buttonfunc에 할당하십시오. 이-> buttonfunc을 사용하려고 할 때 (이제 더 이상 존재하지 않는) 로컬 매개 변수의 저장에 액세스하려고하면 프로그램이 충돌 할 것입니다.

나는 Commodore의 솔루션에 동의합니다. 그러나 당신은 그의 선을 바꿔야합니다

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

buttonobj는 a 바늘 반대하다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top