Мне не нравится, когда магические коробки разбросаны по всему моему коду ... как именно работают эти два класса, чтобы позволить сопоставить практически любую функцию с объектом функции, даже если функция <> имеет совершенно другой параметр, установленный на тот, который я передаю boost::bind
Он даже работает с различными соглашениями о вызовах (т.е. методы-члены находятся __thiscall
в VC, но «обычные» функции обычно __cdecl
или __stdcall
для тех, которые должны быть совместимы с C.
c++
boost
boost-bind
boost-function
Fire Lancer
источник
источник
Ответы:
boost::function
позволяетoperator()
связать что-либо с правильной подписью в качестве параметра, а результат вашей привязки может быть вызван с параметромint
, поэтому он может быть привязан кfunction<void(int)>
.Вот как это работает (это описание одинаково применимо
std::function
):boost::bind(&klass::member, instance, 0, _1)
возвращает такой объектstruct unspecified_type { ... some members ... return_type operator()(int i) const { return instance->*&klass::member(0, i); }
где
return_type
иint
выводятся из сигнатурыklass::member
, а указатель функции и связанный параметр фактически хранятся в объекте, но это не важноТеперь
boost::function
не выполняет никакой проверки типов: он принимает любой объект и любую подпись, которую вы указываете в параметре шаблона, и создает объект, который может быть вызван в соответствии с вашей подписью, и вызывает этот объект. Если это невозможно, это ошибка компиляции.boost::function
на самом деле такой объект:template <class Sig> class function { function_impl<Sig>* f; public: return_type operator()(argument_type arg0) const { return (*f)(arg0); } };
где
return_type
иargument_type
извлекаются изSig
, иf
динамически размещается в куче. Это необходимо, чтобы разрешить привязку к совершенно несвязанным объектам разного размераboost::function
.function_impl
это просто абстрактный классtemplate <class Sig> class function_impl { public: virtual return_type operator()(argument_type arg0) const=0; };
Класс, который выполняет всю работу, является конкретным производным классом
boost::function
. Есть по одному для каждого типа объекта, которому вы назначаетеboost::function
template <class Sig, class Object> class function_impl_concrete : public function_impl<Sig> { Object o public: virtual return_type operator()(argument_type arg0) const=0 { return o(arg0); } };
Это означает, что в вашем случае назначение функции boost:
function_impl_concrete<void(int), unspecified_type>
(конечно, это время компиляции)Когда вы вызываете объект функции, он вызывает виртуальную функцию своего объекта реализации, которая направляет вызов вашей исходной функции.
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: обратите внимание, что имена в этом объяснении намеренно придуманы. Любое сходство с реальными людьми или персонажами ... вы это знаете. Целью было проиллюстрировать принципы.
источник
arg0) const=0 { return...
... Я никогда такого раньше не видел. Я нашел один нефункционирующий пример на форуме, где последующее сообщение, связанное с C ++ faq, объясняет, что чистая виртуальная функция может иметь тело, но я не могу получить код для компиляции с использованием такого синтаксиса (clang & gcc).=0;
телом, указанным позже (например,void Base::Blah() { /* ... */ }
) ... Я конкретно спрашиваю об использованной выше нотации; Полагаю, это просто опечатка.