Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Nie-statyczna metoda jako event

Ostatnio zmodyfikowano 2017-05-25 14:17
Autor Wiadomość
Szustarol
Temat założony przez niniejszego użytkownika
Nie-statyczna metoda jako event
» 2017-05-24 14:18:27
Witam!
Chciałem zaimplementować prosty system eventów, i wszystko się póki co udaje, ale nie mogę wysłać do kontenera metod, które nie są statyczne
myślę, że kod wyjaśni, o co chodzi:
main:
C/C++
#include <SFML/Graphics.hpp>
#include "Object.hpp"
#include <iostream>

void test()
{
    std::cout << "test" << std::endl;
}

int main( int argc, char ** argv )
{
    Object obj1;
    obj1.addEvent( test );
    //obj1.addEvent(obj1.test1);  <--- nie przejdzie
    obj1.click();
    return 0;
}

I w mainie sypie błąd:
error: invalid use of non-static member function

Object.hpp:
C/C++
#ifndef OBJECT_H
#define OBJECT_H
#include <vector>
#include <iostream>

class Object
{
private:
    std::vector < void( * )( void ) > clickEvents;
public:
    Object();
    ~Object();
    void addEvent( void( & f )( void ) );
    void click();
   
    void test1()
    {
        std::cout << "test from an object" << std::endl;
    }
};

#endif // OBJECT_H

i object .cpp
C/C++
#include "Object.hpp"

Object::Object()
{
}

Object::~Object()
{
}

void Object::addEvent( void( & f )( void ) )
{
    this->clickEvents.push_back( f );
}

void Object::click()
{
    for( auto && r: this->clickEvents )
    {
        r();
    }
}

Ja wiem, że event-driven programming to niekoniecznie musi być c++ ale wiem że to napewno jakoś możliwe więc proszę o pomoc :)
P-161520
Monika90
» 2017-05-24 14:43:59
C/C++
std::vector < std::function < void() >> click_handlers;

click_handlers.push_back([ & obj1 ] { obj1.test(); } );
Mam nadzieję że to ci wystarczy.
P-161522
Rashmistrz
» 2017-05-24 14:50:49
Przeanalizuj kod: » Kurs C++ » Poziom XWskaźnik na metodę lekcja
_________________________________________________________________

Mam problem, bo nie rozumiem pojęcia referencji na metodę.
Why doesn't reference-to-member exist in C++?
Reference to member function?
There is no “reference-to-member” type in C++.

Is the type of “pointer-to-member-function” different from “pointer-to-function”? 

std::vector < void( * )( void ) > clickEvents;
 na
std::vector < void( Object::* )( void ) > clickEvents;
.

void addEvent( void( & f )( void ) );
 na
void addEvent( void( Object::* f )( void ) );
.
___________________________________________________________________

Metoda musi być wykonana na obiekcie danej klasy.
Jako że jest to wskaźnik na niestatyczną metodę to (jak kompilator mi powiedział):
must use '.*' or '->*' to call pointer-to-member function in 'r (...)', e.g. '(... ->* r) (...)'
r();
 zamienić na
* this.* r();
 lub
this->* r();
.

(» Programowanie obiektowe, C++ » PodstawyStatyczne zmienne i metody w klasie lekcja)
Wyjątkiem jest metoda statyczna. Co by Ci pozwoliło na:
r();
.
Wskaźnik na statyczną metodę zachowuje się tak samo jak wskaźnik na normalną funkcję.
Z tym wyjątkiem, że znajduje się znajduje się w przestrzeni adresowej klasy.

Object::test();
, gdyby test była metodą statyczną.
Więc tak uzyskiwałoby się wskaźnik:
& Object::test
,
jakby Object był przestrzenią nazw.

(How to define a function pointer pointing to a static member function?)
___________________________________________________________________

Nawiązując do mojego mojego starego tematu (adres adresu funkcji)...
Niejawna konwersja funkcji na wskaźnik na funkcję
nie zachodzi w przypadku metod.

obj1.addEvent( Object::test1 );
 na
obj1.addEvent( & Object::test1 );
.
___________________________________________________

Oto jak posiekałem twój kod,
który się u mnie kompiluje:
C/C++
// Example program
#include <vector>
#include <iostream>

class Object
{
private:
    typedef void( Object::* Event )( void );
    std::vector < Event > clickEvents;
public:
    Object() { };
    ~Object() { };
    void addEvent( Event event ) { clickEvents.push_back( event ); }
    void click() { for( auto && clickEvent: clickEvents )( this->* clickEvent )(); };
   
    void event() { std::cout << "clickEvent happened!" << std::endl; }
};

int main( int argc, char ** argv )
{
    Object object;
    object.addEvent( & Object::event );
    object.click();
    return 0;
}
Z góry przepraszam za czytelność.

EDIT1:
Zły możesz być tylko na DejaVu,
że nie dał funkcji podglądu. ;D

EDIT2:
Tak BTW dlaczego nie możesz stworzyć wektora referencji:
Why can't I make a vector of references?
Ale jak widać niżej, ktoś ma dla Ciebie rozwiązanie. :)

EDIT3: Zbieram podziękowania do kolekcji. :D
P-161524
1aam2am1
» 2017-05-24 17:21:48
C/C++
std::vector < std::function < void() >> click_handlers;

Obiekt obiekt;
click_handlers.push_back( std::bind( & Obiekt::test1, std::ref( obiekt ) ) );
P-161537
Szustarol
Temat założony przez niniejszego użytkownika
» 2017-05-25 14:17:59
Wielkie dzięki za odpowiedzi, temat jest szerszy niż się spodziewałem.
Fajnie, że w c++ nawet po dłuższym czasie nauki wciąż można znaleźć coś nowego
P-161565
« 1 »
  Strona 1 z 1