Nie podoba mi się, gdy magiczne pola są rozrzucone po całym kodzie ... jak dokładnie te dwie klasy działają, aby w zasadzie umożliwić mapowanie dowolnej funkcji na obiekt funkcji, nawet jeśli funkcja <> ma zupełnie inny parametr ustawiony niż ten, do którego przechodzę boost::bind
Działa nawet z różnymi konwencjami wywoływania (tj. Metody składowe są __thiscall
objęte VC, ale „normalne” funkcje są generalnie __cdecl
lub __stdcall
dla tych, które muszą być zgodne z C.
c++
boost
boost-bind
boost-function
Ognisty Lancer
źródło
źródło
Odpowiedzi:
boost::function
pozwala, aby wszystko, co maoperator()
właściwą sygnaturę, zostało powiązane jako parametr, a wynik powiązania można wywołać z parametremint
, więc można go powiązaćfunction<void(int)>
.Oto jak to działa (ten opis dotyczy również
std::function
):boost::bind(&klass::member, instance, 0, _1)
zwraca obiekt taki jak tenstruct unspecified_type { ... some members ... return_type operator()(int i) const { return instance->*&klass::member(0, i); }
gdzie
return_type
iint
są wywnioskowane z podpisuklass::member
, a wskaźnik funkcji i powiązany parametr są w rzeczywistości przechowywane w obiekcie, ale to nie jest ważneTeraz
boost::function
nie wykonuje żadnego sprawdzenia typu: weźmie dowolny obiekt i każdy podpis, który podasz w parametrze szablonu i utworzy obiekt, który można wywołać zgodnie z Twoim podpisem i wywoła obiekt. Jeśli to niemożliwe, jest to błąd kompilacji.boost::function
to właściwie taki obiekt:template <class Sig> class function { function_impl<Sig>* f; public: return_type operator()(argument_type arg0) const { return (*f)(arg0); } };
gdzie
return_type
iargument_type
są wyodrębniane zSig
if
jest dynamicznie przydzielane na stercie. Jest to konieczne, aby umożliwić powiązanie całkowicie niepowiązanych obiektów o różnych rozmiarachboost::function
.function_impl
to tylko klasa abstrakcyjnatemplate <class Sig> class function_impl { public: virtual return_type operator()(argument_type arg0) const=0; };
Klasa, która wykonuje całą pracę, jest konkretną klasą pochodną
boost::function
. Istnieje po jednym dla każdego typu obiektu, do którego przypisujeszboost::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); } };
Oznacza to w twoim przypadku przypisanie do funkcji boost:
function_impl_concrete<void(int), unspecified_type>
(to oczywiście czas kompilacji)Kiedy wywołujesz obiekt funkcji, wywołuje on funkcję wirtualną swojego obiektu implementacji, która skieruje wywołanie do twojej oryginalnej funkcji.
ZRZECZENIE SIĘ: Należy pamiętać, że nazwy w tym wyjaśnieniu są celowo wymyślone. Jakiekolwiek podobieństwo do prawdziwych osób lub postaci ... wiesz o tym. Celem było zilustrowanie zasad.
źródło
arg0) const=0 { return...
... nigdy wcześniej tego nie widziałem. Znalazłem jeden niedziałający przykład na forum, gdzie wiadomość uzupełniająca związana z C ++ faq wyjaśniająca, że czysta funkcja wirtualna może mieć ciało, ale nie mogę uzyskać żadnego kodu do kompilacji przy użyciu takiej składni (clang i gcc).=0;
ciałem podanym później (np.void Base::Blah() { /* ... */ }
) ... Pytam konkretnie o zastosowaną powyżej notację; Domyślam się, że to tylko literówka.