Используйте указатель на функцию как прокси для функции-члена - PullRequest
0 голосов
/ 23 сентября 2019

Предположим, что класс подобен этому:

class Speaker {
    public:
        void (*saySomething)();
}

Дело в том, что мы можем создать экземпляр этого класса и вызвать указатель сохраненной функции, чтобы он что-то говорил (каким бы он ни был).Основой такого подхода является наличие фактической функции в общей библиотеке, а Speaker действует как своего рода класс-оболочка (функция разрешается в библиотеке, и указатель назначается переменной в классе).

Теперь рассмотрим, что у нас есть другой класс, который расширяет Speaker:

class ConstantSpeaker : public Speaker {
    protected:
        std::string message;
        void doSpeak();
}

с реализацией метода следующим образом:

ConstantSpeaker::doSpeak() {
    std::cout << message << std:endl;
}

Теперь я хочу присвоить saySomething указатель таким образом, что вызов каким-то образом перенаправляется на ConstantSpeaker::doSpeak().Это, однако, невозможно напрямую, поскольку doSpeak() является функцией-членом, а saySomething является указателем на функцию, не являющуюся членом.
Другая идея, которую я имел, заключалась в создании doSpeak() в качестве функции-друга ConstantSpeaker вместо.Тогда назначение указателя работает нормально, но теперь doSpeak() требует, чтобы объект содержал реальное сообщение в качестве аргумента, чтобы иметь возможность доступа к сообщению.

Мне кажется, что должен быть (более или менее) прямой способ сделать это, учитывая, что я могу звонить Speaker::saySomething только когда у меня есть экземпляр Speaker под рукой.Поэтому наличие соответствующего объекта не должно быть проблемой, но все же я не могу понять, как я должен назначить этот указатель.

Единственное решение, которое я мог придумать, - это добавить общедоступную функцию virtual Speaker::doSaySomething, реализация которой будет вызывать указатель функции (который больше не является общедоступным для предотвращения неправильного использования) и которая может быть перезаписанапо ConstantSpeaker вместо ConstantSpeaker::doSpeak().
Есть ли другое решение этой проблемы?

1 Ответ

2 голосов
/ 23 сентября 2019

Другое решение состоит в том, чтобы просто использовать стандартный std::function<void()>, и тогда он все еще может быть объявлен как открытый.

Кроме того, вместо пустого указателя функции вы можете использовать указатель на функцию-член, но помнитео нарезке, при использовании его внутри базового класса.

Но, я думаю, самый простой способ сделать это - просто использовать функцию virtual, как вы упомянули.

Может, расскажете подробнее о вашем контексте?Какую проблему вы собираетесь решить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...