przejście do zawartości
Jan Kończak
Narzędzia użytkownika
Zaloguj
Narzędzia witryny
Narzędzia
Pokaż stronę
Poprzednie wersje
Odnośniki
Ostatnie zmiany
Menadżer multimediów
Indeks
Zaloguj
Ostatnie zmiany
Menadżer multimediów
Indeks
Jesteś tutaj:
start
»
sk2
»
memberptrs_bind
sk2:memberptrs_bind
Ta strona jest tylko do odczytu. Możesz wyświetlić źródła tej strony ale nie możesz ich zmienić.
=== Wskaźnik na metodą z klasy === <code cpp> QLineEdit * le = new QLineEdit; // wskaźnik na funkcję z klasy: void (QLineEdit::*leMethod1) () = &QLineEdit::clear; // wywołanie takiego wskaźnika na rzeczy obiektu le: (le->*leMethod1)(); // to samo, z argumentem: void (QLineEdit::*leMethod2) (bool) = &QLineEdit::setEnabled; (le->*leMethod2)(true); </code> Wyjaśnienie: * ''<wynik> (*) (<argumenty>)'', np: ''void (*) (int)'' ← typ dla zwykłej funkcji * ''<wynik> (<Klasa>::*) (<argumenty>)'', np: ''void (A::*) (int)'' ← typ dla metody z obiektu * ''<wynik> (<Klasa>::*nazwa) (<argumenty>)'', np: ''void (A::*m) (int)'' ← zmienna powyższego typu * dla zwykłych (nie wirtualnych) metod kompilator wyznacza którą metodę (znajdującą się pod znanym na etapie kompilacji adresem) ma wywołać na rzecz obiektu. * dla wirtualnych metod kompilator wylicza pozycję w [[https://en.wikipedia.org/wiki/Virtual_method_table|tabeli metod wirtualnych]] którą należy wywołać. === Ręczne połączenie metody z obiektem === <code cpp> template <typename T> struct opakowanie { T * obiekt; void (T::*metoda) (bool); void operator()(bool arg){ (obiekt->*metoda)(arg); } }; void someCode(){ QLineEdit * le = new QLineEdit; opakowanie<QLineEdit> box {le, &QLineEdit::setEnabled}; box(true); } </code> === Bind - połączenie metody na rzecz obiektu === <code cpp> #include <functional> void someCode(){ QLineEdit * le = new QLineEdit; auto box = std::bind(&QLineEdit::setEnabled, le, std::placeholders::_1); box(true); std::function<void (bool)> func = std::bind(&QLineEdit::setEnabled, le, std::placeholders::_1); func(true); // box i func są różnych typów (func opakowuje box) } </code> Formalnie bind to [[https://en.wikipedia.org/wiki/Partial_application|częściowe wykonanie]] metody\\ Dostępny w boost (''boost::bind'') od 2001 roku, włączony w standard C++11 W środku std::bind w GCC działa podobnie jak powyższy przykład; identyfikacja typu przez gdb: <code> (gdb) ptype box type = struct std::_Bind<std::_Mem_fn<void (QWidget::*)(bool)>(QLineEdit*, std::_Placeholder<1>)> [with _Signature = std::_Mem_fn<void (QWidget::*)(bool)> (QLineEdit *, std::_Placeholder<1>)] : public std::_Weak_result_type<std::_Mem_fn<void (QWidget::*)(bool)> > { private: std::_Mem_fn<void (QWidget::*)(bool)> _M_f; std::tuple<QLineEdit*, std::_Placeholder<1> > _M_bound_args; public: _Bind(const std::_Bind<std::_Mem_fn<void (QWidget::*)(bool)>(QLineEdit*, std::_Placeholder<1>)> &); _Bind(<unknown type in /home/user/build-test-Desktop_qt5-Debug/test, CU 0x42cc0, DIE 0x4e548>); void operator()<bool, void>(<unknown type in /home/user/build-test-Desktop_qt5-Debug/test, CU 0x42cc0, DIE 0x4e57b>); void _Bind<QLineEdit*&, std::_Placeholder<1> const&>(<unknown type in /home/user/build-test-Desktop_qt5-Debug/test, CU 0x42cc0, DIE 0x4e5ae>, QLineEdit *&, const std::_Placeholder<1> &); private: void __call<void, bool&&, 0ul, 1ul>(<unknown type in /home/user/build-test-Desktop_qt5-Debug/test, CU 0x42cc0, DIE 0x4e605>, std::_Index_tuple<0ul, 1ul>); } </code> === Bind z ustalenie wartości części argumentów (bez metody z obiektu): === <code cpp> #include <unistd.h> #include <functional> using namespace std::placeholders; void someCode(){ char buf[255]; std::function<ssize_t (int)> simpleRead = std::bind(read, std::placeholders::_1, buf, 255); simpleRead(0); std::function<ssize_t (void*, size_t)> stdinRead = std::bind(read, 0, std::placeholders::_1, std::placeholders::_2); stdinRead(buf, 255); }</code> Argumenty można podawać przez wartość lub jako referencja opakowane w ''std::ref'' / ''std::cref''. === Dlaczego connect był złym przykładem na wskaźnik do funkcji z klasy: === <code cpp> QLineEdit *le = new QLineEdit; // 1) stara składnia connect jest static, nie ma potrzeby definiowania wskaźnika na metodę z klasy: QMetaObject::Connection (*method1) (const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType) = &QObject::connect; method1(le, SIGNAL(returnPressed()), le, SLOT(clear()), Qt::AutoConnection); // 2) nowa składnia poza tym ze też jest static, to jest oparta na template'ach, więc trzeba jakiś zrealizować: QMetaObject::Connection (*method2) (const QLineEdit *, void (QLineEdit::*)(), const QLineEdit *, void (QLineEdit::*)(), Qt::ConnectionType) = &QObject::connect; method2(le, &QLineEdit::returnPressed, le, &QLineEdit::clear, Qt::AutoConnection); // 3) lepiej to wygląda z typedef: typedef QMetaObject::Connection (*newtype) (const QLineEdit *, void (QLineEdit::*)(), const QLineEdit *, void (QLineEdit::*)(), Qt::ConnectionType); newtype method3 = &QObject::connect; method3(le, &QLineEdit::returnPressed, le, &QLineEdit::clear, Qt::AutoConnection); </code>
sk2/memberptrs_bind.txt
· ostatnio zmienione: 2016/11/22 21:48 przez
jkonczak
Narzędzia strony
Pokaż stronę
Poprzednie wersje
Odnośniki
Złóż / rozłóż wszystko
Do góry