Как передать указатель на член внутри класса во внешний класс? - PullRequest
0 голосов
/ 01 октября 2019

Я пытаюсь передать указатель на член класса (Dialog :: handler) из его метода (в области Dialog :: render) на какой-то внешний метод (Button :: OnClick).

ЗдесьВот небольшой пример:

        class Button
        {
        public:
            void OnClick(void (*handler)())
            {
                handler();
            }
        };

        class Dialog
        {
        public:
            void handler()
            {
                //do stuff
            }
            void render()
            {
                auto button = new Button;
                //Source of problem
                button->OnClick(this->*handler);
            }
        };

Но компилятор показывает ошибку:

нестандартный синтаксис;используйте '&' для создания указателя на член

Также я использую другие комбинации, такие как:

  • обработчик this->.
  • & this.handler.
  • this. * Обработчик.
  • и т. Д.

Но, очевидно, они потерпели неудачу.

1 Ответ

3 голосов
/ 01 октября 2019

Вы можете использовать std::function и передать ему лямбду, в которой вы поймали this объекта, который вы хотите перезвонить:

#include <functional>
#include <iostream>

class Button {
public:
    void OnClick(std::function<void()> handler) {
        handler();
    }
};

class Dialog {
public:
    void handler() {
        std::cout << "Dialog::handler\n";
    }
    void render() {
        auto button = new Button;
        // a lambda catching "this" Dialog.
        button->OnClick([this] { this->handler(); });
        delete button;                               // you didn't delete your button
    }
};

int main() {
    Dialog d;
    d.render();
}

Но похоже,вам, вероятно, следует наследовать от общего базового класса, который имеет virtual void handler(), чтобы вы могли вместо этого передавать указатели / ссылки на объекты. Грубая идея:

#include <iostream>

class VisualBase {
public:
    virtual void handler() = 0;
    virtual ~VisualBase() = 0;
};

VisualBase::~VisualBase() {}

class Button : public VisualBase {
public:
    void handler() override {}

    void OnClick(VisualBase* caller) {
        caller->handler(); 
    }
};

class Dialog : public VisualBase {
public:
    void handler() override { 
        std::cout << "Dialog::handler\n"; 
    }

    void render() {
        Button button;
        button.OnClick(this);
    }
};

int main() {
    Dialog d;
    d.render();
}
...