• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Błąd kompilatora, odwoływanie się do funkcji a do metody.

VPS Starter Arubacloud
0 głosów
245 wizyt
pytanie zadane 23 sierpnia 2015 w C i C++ przez Dash Nałogowiec (29,650 p.)

Napotkałem dziwny błąd kompilatora, nie mam pojęcia jak naprawic kod. Oto i on: 

||=== Build: Debug in SFML_TEST (compiler: Copy of GNU GCC Compiler) ===|

E:\ZZZ\SFML_TEST\efekt.h|46|error: no matching function for call to 'thor::CallbackTimer::connect0(void (Efekt_podpalenie::*)())'|
E:\BIBLIOTEKI\THOR\include\Thor\Time\CallbackTimer.hpp|104|note: candidate: thor::Connection thor::CallbackTimer::connect0(std::function<void()>)|
E:\BIBLIOTEKI\THOR\include\Thor\Time\CallbackTimer.hpp|104|note:   no known conversion for argument 1 from 'void (Efekt_podpalenie::*)
||=== Build failed: 1 error(s), 14 warning(s) (0 minute(s), 1 second(s)) ===|

 

Jeżeli dobrze rozumiem, to oczekiwana jest zwykła funkcja a nie metoda klasy. W dokumentacji (http://www.bromeon.ch/libraries/thor/v2.0/doc/classthor_1_1_callback_timer.html) 

nie ma niestety przykładu w OOP. Jeżeli można, to czego ten błąd tak dokładnie dotyczy? 

 

1 odpowiedź

+1 głos
odpowiedź 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)
Bład dotyczy tego, że do funkcji wysyłasz argument niewłaściwego typu bez zdefiniowanej konwersji do typu oczekiwanego podaj linikę, w kótrej wywala błąd(46)
komentarz 23 sierpnia 2015 przez Dash Nałogowiec (29,650 p.)

timer.connect0( &listener );

gdzie listener to funkcja void klasy Efekt_podpalenie a timer to obiekt klasy z zewnętrznej biblioteki. 

timer.connect0 oczekuje adresu funkcji do wywołania. Jako że nie używam go  w main.cpp tylko w obiekcie nie wiem jak ten argument wysłać (jakiej składni uzyć). 

Teoretcznie robi się to tak : 

 #include <Thor/Time/CallbackTimer.hpp>
 #include <iostream>
 
 void listener(thor::CallbackTimer& trigger) //alternatywnie listener0, która nic nie otrzymuje
 {
     std::cout << "expired" << std::endl;
     trigger.restart(sf::seconds(1.f));
 }
 
 int main()
 {
     thor::CallbackTimer timer;
     timer.connect(&listener);
     timer.restart(sf::seconds(1.f));
 
     for (;;)
         timer.update();
 }

 

 

 

komentarz 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)

Myślę, że wiem o co chodzi mamy klasę o nazwie załużmy obj i ona ma metodę void listener(thor::CallbackTimer& trigger) delkaraca zmiennej obj object. Skoro funkcja connect0 wymaga adresu tej funckji to jej wywołanie powinno wyglądać

timer.connect0( &(object.listener(thor::CallbackTimer& trigger));
//lub powinno też działać
timer.connect0(object.listener);

chyba że jest to metoda statyczna to zamiast object. daj obj:: i powinno działać

komentarz 23 sierpnia 2015 przez adrian17 Ekspert (349,960 p.)
timer.connect0( &(object.listener(thor::CallbackTimer& trigger));
//lub powinno też działać
timer.connect0(object.listener);

Prawdopodobnie żadne z nich się nie skompiluje.

Ja bym owinął wywołanie metody w lambdę, minimalny przykład:

#include <functional>
struct CallbackTimer{ // zacytowane z dokumentacji
	void connect(std::function< void(CallbackTimer &)>){}
};

struct Efekt_podpalenie{
	void listener(CallbackTimer& trigger){}
};

int main(){
	Efekt_podpalenie obiekt;
	CallbackTimer timer;
	timer.connect(
		[&](CallbackTimer &trigger){
			obiekt.listener(trigger);
		}
	);
}

timer.connect0 oczekuje adresu funkcji do wywołania.

Konkretniej wymaga obiektu std::function, który może się skonstruować między innymi z adresu funkcji.

komentarz 23 sierpnia 2015 przez Dash Nałogowiec (29,650 p.)
edycja 23 sierpnia 2015 przez Dash
@EDIT

Pomysł Adriana działa perfekcyjnie, a szczerze mówiąc pierwszy raz widzę czym są wyrażenia lambda w c++. Człowiek ciągle się czegoś uczy :).

Serdzecznie wszystkim dziękuję!
komentarz 23 sierpnia 2015 przez adrian17 Ekspert (349,960 p.)
(cóż, lambdy powstały między innymi właśnie po to żeby umożliwić robienie czegoś takiego w prosty sposób :P Ewentualnie jeszcze std::bind który robi to samo ale mniej.)
komentarz 23 sierpnia 2015 przez Szykem2 Nałogowiec (29,510 p.)

Sprawdziłem to i rzeczywiście standard nie zezwala utwożenia wskaźnika do metody składowej klasy ale jak zmienisz ją na metodę statyczną i i wywołanie timer.connect0(&(obj::listener));

komentarz 23 sierpnia 2015 przez Dash Nałogowiec (29,650 p.)
Tak, zajęło mi chwilę zatrybienie że używasz struktur zamiast klas (także pierwszy raz takie coś widzę), pierwotnie myslałem że muszę deklarować nowe struktury dla każdej klasy, a następnie na tym operować i tak dalej - skomplikowane i nieefektywne.

Tak czy siak, dzięki :)
komentarz 23 sierpnia 2015 przez adrian17 Ekspert (349,960 p.)
Ach, przepraszam, typowo w przykładach używam struct zamiast class bo funkcjonalnie robią dokładnie to samo a zyskuję jedną linię bo nie muszę pisać "public:" bo domyślnie wszystko jest publiczne.
komentarz 23 sierpnia 2015 przez Dash Nałogowiec (29,650 p.)
Takie pytanko tylko, od zawsze struktury mogły posiadać funkcje czy to jakaś nowość w c++11? Z tego co pamiętam to w mojej książce było wspomniane że tak jak np. Unie mogą przechowywać jedynie zmienne.

Jak chcesz to moze odpowiesz w osobnym poście i skopiujesz rozwiązanie problemu, z chęcią dałbym Ci najlepszą odpowiedź, żeby w przyszłości ludzie mogli to szybko znaleźć.
komentarz 23 sierpnia 2015 przez adrian17 Ekspert (349,960 p.)
Od zawsze w C++ struct i class oznaczały praktycznie to samo i można było z nimi robić to samo, jedyną różnicą są domyślne poziomy dostępu (public/private) i dostępu przy dziedziczeniu.

Podobne pytania

0 głosów
1 odpowiedź 390 wizyt
pytanie zadane 16 lipca 2022 w C i C++ przez HUBSON2912 Obywatel (1,460 p.)
+1 głos
1 odpowiedź 368 wizyt
pytanie zadane 25 lutego 2020 w Python przez PIxEL Nowicjusz (180 p.)
0 głosów
2 odpowiedzi 251 wizyt

93,024 zapytań

141,986 odpowiedzi

321,290 komentarzy

62,371 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj

Wprowadzenie do ITsec, tom 2

Można już zamawiać tom 2 książki "Wprowadzenie do bezpieczeństwa IT" - będzie to około 650 stron wiedzy o ITsec (17 rozdziałów, 14 autorów, kolorowy druk).

Planowana premiera: 30.09.2024, zaś planowana wysyłka nastąpi w drugim tygodniu października 2024.

Warto preorderować, tym bardziej, iż mamy dla Was kod: pasja (użyjcie go w koszyku), dzięki któremu uzyskamy dodatkowe 15% zniżki! Dziękujemy zaprzyjaźnionej ekipie Sekuraka za kod dla naszej Społeczności!

...