Предположим, что класс подобен этому:
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()
.
Есть ли другое решение этой проблемы?