Prefer dobrze określony interfejs na callbacków
Problem std::function
(poprzednio boost::function
) jest to, że w większości przypadków trzeba mieć zwrotną metody klasy, a więc trzeba wiązać this
do obiektu funkcji. Jednak w kodzie wywołującym nie masz możliwości sprawdzenia, czy nadal jest w pobliżu this
. W rzeczywistości nie masz pojęcia, że istnieje nawet this
, ponieważ bind ukształtował sygnaturę funkcji wywołującej w to, czego żąda wywołujący.
Może to oczywiście powodować dziwne awarie, ponieważ wywołanie zwrotne próbuje uruchomić metody dla klas, które już nie istnieją.
Możesz, oczywiście, użyć shared_from_this
i powiązać shared_ptr do wywołania zwrotnego, ale wtedy twoja instancja może nigdy nie zniknąć. Osoba, która ma do ciebie telefon oddzwaniowy, teraz bierze udział w twoim posiadaniu, nawet nie wiedząc o tym. Prawdopodobnie chcesz bardziej przewidywalne własności i zniszczenia.
Kolejny problem, nawet jeśli można uzyskać oddzwonienie, aby działał poprawnie, jest z wywołania zwrotnego, kod może być zbyt oddzielone od siebie. Relacje między obiektami mogą być tak trudne do stwierdzenia, że czytelność kodu zmniejsza się. Interfejsy zapewniają jednak dobry kompromis między odpowiednim poziomem rozłączenia a jasno określoną relacją, zgodnie z definicją umowy interfejsu. Możesz także bardziej precyzyjnie określić, w tym związku, kwestie, kto jest właścicielem kogo, porządek destrcution itp.
Dodatkowym problemem z std::function
jest to, że wiele debuggerów nie obsługuje ich dobrze. W VS2008 i funkcjach doładowania musisz przejść przez około 7 warstw, aby dostać się do swojej funkcji. Nawet jeśli wszystkie inne rzeczy są równe, najlepszym rozwiązaniem był oddzwonienie, zwykła irytacja i czas zmarnowany przypadkowo przekraczanie celu std::function
jest wystarczającym powodem, aby tego uniknąć. Dziedziczenie jest podstawową cechą języka, a przejście na nadpisaną metodę interfejsu jest natychmiastowe.
Na koniec dodam tylko , nie mamy delegatów w C++. Delegaci w C# stanowią rdzeń języka, podobnie jak dziedziczenie jest w C++ i C#. Mamy funkcję biblioteki standardowej, którą IMO stanowi jedna warstwa usunięta z funkcji języka podstawowego. Więc nie będzie tak ściśle zintegrowany z innymi podstawowymi funkcjami tego języka. Zamiast tego pomaga sformalizować ideę obiektów funkcyjnych, które od dawna są idiomem C++.
W jaki sposób 'std :: function' różni się od wskaźników funkcyjnych (* w tym kontekście *)? Nie widzę żadnej różnicy. Jeśli tak, to co to ma z C++ 11? Można również użyć wskaźników funkcyjnych do implementacji polimorfizmu runtime w pre-C++ 11. – Nawaz
Nie jestem nawet pewien, jak rozpocząć odpowiadanie ... na przykład funkcja std :: może zawierać wskaźnik do funkcji o innym typie i liczbie argumentów, ponieważ możesz std :: bindować je przed faktycznym przekazaniem do niego. I oczywiście jest to prostsze w użyciu. Jeśli mógłbyś cokolwiek zapytać o to, co może zrobić to, czego nie potrafią faceci ... to pytanie zrozumiałbym. Mimo to, dodanie standardowego i * prostego * sposobu na tworzenie delegatów jest tak czy inaczej przyczyną mojego pytania. – Zeks
"* Nadal, oprócz standardowego i prostego sposobu tworzenia delegatów, to i tak zrodziło się moje pytanie. *" ... Ale to * nie jest prostsze * niż używanie abstrakcyjnych funkcji bazowych i wirtualnych, więc jaki jest sens? – Nawaz