mess with pointers

hello everybody
i'm making a(nother) mess with pointers and addresses. this time i want to make a simple SFML application.
here is a simplified code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class GameSys{
    sf::Event game_events;

    public:
    sf::Event* getGameEvents();
};
sf::Event* GameSys::getGameEvents(){
    return &game_events;
}

class Game{
    GameSys* p_gamesys;

    public:
    int runGame();
    Game(GameSys*);
    ~Game();
};

int Game::runGame(){
    while (p_gamesys->getGameWindow()->pollEvent(p_gamesys->getGameEvents())){

        sf::CircleShape shape(100.f);
        shape.setFillColor(sf::Color::Green);
        p_gamesys->getGameWindow()->draw(shape);

        drawGame();
        if (p_gamesys->getGameEvents()->type == sf::Event::Closed)
                p_gamesys->getGameWindow()->close();
        }
    return 0;
}

Game::Game(GameSys* ptr){
    p_gamesys = ptr;
}


int main(){
    GameSys gamesys;
    Game game(&gamesys);
    game.runGame();
    return 0;
}


if i run it, i get:

error: no matching function for call to sf::RenderWindow::pollEvent(sf::Event*)
candidate is: bool sf::Window::pollEvent(sf::Event&)
can't convert ‘sf::Event*’ to ‘sf::Event&’


now, it asks as argument an address, but it seems that i'm using a pointer. how to fix it? pointers blow my head.
thanks in advance!
The function is asking for a reference of a sf::Event.

You could just dereference your pointer.

 
pollEvent( *(p_gamesys->getGameEvents()) );
ok, i tried it and it works.
but would you mind to explain why?

i did create the function, which return an address; the function asks for a reference; isn't the address a reference to sf::Event object game_event?

thanks!
If a function has a reference parameter it's not expecting a pointer. It's just expecting a reference of a type, so you pass it a normal type.

1
2
3
4
5
6
7
8
void someFunc( int &n )
{
   n += 10;
}

// call
int a = 5;
someFunc( a );


All that's happening is that the function isn't creating a copy of the argument for local use. It's using the one at the address that has been passed to it.

Don't forget; pointers and references are not the same thing.
ok, but if pointers and references are not the same thing, how can i create a function which is of the pointer type (sf::Event* GameSys::getGameEvents()) and it successfully return an address (return &game_events;)?

thanks for the help :)

EDIT:
oh, i'm sticking to the manual from this site, which says:
& can be read as "address of"
* can be read as "value pointed by"


SO, i did create the function that return an address.
later, i want to get the value stored in that address (in this case, the object sf::Event);

doesn't the -> makes it jump from the pointer directly to the object itself in this line?
p_gamesys->getGameEvents

or is that because i'm jumping from the gamesys pointer to the gamesys object, and then in the function inside the gamesys object just returns another pointer?

geez, is there any idea to make this code a bit cleaner? i just want to have access to the original sf::Event object.

thanks again!
Last edited on
ok, but if pointers and references are not the same thing, how can i create a function which is of the pointer type (sf::Event* GameSys::getGameEvents()) and it successfully return an address (return &game_events;)?

Easily. There are no references involved.


oh, i'm sticking to the manual from this site, which says:
& can be read as "address of"
* can be read as "value pointed by"

This is true only of code which is not an object declaration.


geez, is there any idea to make this code a bit cleaner? i just want to have access to the original sf::Event object.

For one thing you could stop naming a single event object as if it were more than one event (and do the same of the getter function.) Not exposing the event to the rest of the code in this manner would also be nice. Consider using callbacks.
For one thing you could stop naming a single event object as if it were more than one event (and do the same of the getter function.) Not exposing the event to the rest of the code in this manner would also be nice. Consider using callbacks


i don't understand that exactly.
-what do you mean by "baming a single event as if it were more than one"? are you just saying that the variable name should be simplified?
-the event is exposed just where it needs to be. better than that, the only way i see is creating a copy of it everytime the loop runs...
-and how do i use callbacks in this case? can someone show a little piece of code?

thanks again!
-what do you mean by "baming a single event as if it were more than one"? are you just saying that the variable name should be simplified?

I'm saying the variable and getter name could be more accurate. You aren't storing multiple events. You're storing one single event.

-the event is exposed just where it needs to be. better than that, the only way i see is creating a copy of it everytime the loop runs...

I overestimated the scope of what you're trying to do with my first look at the code. The 'event' should be a variable local to Game::runGame. There is no need for it to be a persistent member of a class object. And it is definitely not exposed just where it needs to be. For instance, in main, one may call gamesys.getGameEvents, obtain a pointer to the event object and modify the event object at any time one wishes. There is no reason for that to be possible.



return a reference:
1
2
3
4
5
6
7
class Integer
{
  int my_int;

  public:
  int& get(void) { return my_int; }
};
-and how do i use callbacks in this case? can someone show a little piece of code?

Again, I think I overestimated what you were trying to accomplish and that callbacks may be a bit beyond what you can handle at this point, however, the following code (which requires C++11) shows a simple event handler that uses callbacks and SFML. It simply draws some circles on the screen when you press the right mouse button and drag the mouse around.

Notable language features used which you may not be familiar with are:
* std::function which stores a callable function object (whether it is a function pointer, a functor (which is a class with operator() defined) or a lambda)
* lambdas which are unnamed function objects.
* range-based for loop
* C++11 random number generator/distribution

Useful links for understanding usage of the above:
http://en.cppreference.com/w/cpp/utility/functional/function
http://stackoverflow.com/questions/7627098/what-is-a-lambda-expression-in-c11
http://www.cprogramming.com/c++11/c++11-ranged-for-loop.html
http://stackoverflow.com/questions/7114043/random-number-generation-in-c11-how-to-generate-how-do-they-work

You can probably ignore the random number stuff/ranged base for loop altogether if you aren't familiar with them. The main thing here is the (rather simple) EventHandler class and how callback function objects are registered via registerCallback. The rest is provided solely to showcase the EventHandler class in the arena you were playing in (SFML.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#include <functional>
#include <unordered_map>
#include <random>
#include <vector>
#include <SFML/Graphics.hpp>

class EventHandler
{
public:
    typedef std::function<void(const sf::Event&)> cb_type ;

    void registerCallback(sf::Event::EventType evType, cb_type cb)
        { _func[evType] = cb ; }

    void processEvents(sf::Window& window) const ;

private:
    typedef std::unordered_map<sf::Event::EventType, cb_type> map_type ;

    map_type _func ;
};

void EventHandler::processEvents(sf::Window& window) const
{
    if ( window.isOpen() )
    {
        sf::Event event ;
        bool closeWindow = false ;

        while ( window.pollEvent(event) )
        {
            map_type::const_iterator handler = _func.find(event.type) ;

            if ( handler != _func.end() )
                handler->second(event) ;

            if ( event.type == sf::Event::Closed )
                closeWindow = true ;
        }

        if ( closeWindow )
            window.close() ;
    }
}

int main(){

    std::default_random_engine rng( (std::random_device()()) ) ;
    std::uniform_int_distribution<unsigned> rndColor(0, 255) ;

    std::vector<sf::CircleShape> dots ;

    bool rightButtonPressed = false ;
    sf::Color bgColor = sf::Color::White ;
    sf::RenderWindow window(sf::VideoMode(600, 400), "EVENT Handling") ;

    EventHandler handler ;
    handler.registerCallback( sf::Event::MouseButtonPressed, 
        [&](const sf::Event& ev)
        { 
            if ( ev.mouseButton.button == sf::Mouse::Right )
            {
                dots.clear() ;
                rightButtonPressed = true ;
            }
        });

    handler.registerCallback( sf::Event::MouseButtonReleased,
        [&](const sf::Event& ev)
        {
            if ( ev.mouseButton.button == sf::Mouse::Right )
                rightButtonPressed = false ;
        });

    handler.registerCallback( sf::Event::MouseMoved,
        [&](const sf::Event& ev)
        {
            if ( rightButtonPressed == true )
            {
                sf::CircleShape circle((rng() % 13)+3) ;
                circle.setOrigin(circle.getRadius(), circle.getRadius()) ;
                circle.setPosition(ev.mouseMove.x, ev.mouseMove.y) ;
                circle.setFillColor(sf::Color(rndColor(rng), rndColor(rng), rndColor(rng))) ;
                dots.push_back(circle) ;
            }
        });

    while ( window.isOpen() )
    {
        handler.processEvents(window) ;

        if ( window.isOpen() )
        {
            window.clear(bgColor) ;

            for ( auto& dot : dots )
                window.draw(dot) ;

            window.display() ;
        }
    }
}
Last edited on
And it is definitely not exposed just where it needs to be. For instance, in main, one may call gamesys.getGameEvents, obtain a pointer to the event object and modify the event object at any time one wishes. There is no reason for that to be possible.

i understand what you say. that is because the code isn't complete, it's simplified. but i need the game_event object outside the runGame() function also.

what concerns me is this (again, not the complete code):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class GameSys{
    sf::RenderWindow game_window;
    sf::Event game_events;

    public:
    sf::RenderWindow* getGameWindow();
    sf::Event* getGameEvents();
};
sf::RenderWindow* GameSys::getGameWindow(){
    return &game_window;
}
sf::Event* GameSys::getGameEvents(){
    return &game_events;
}

[some other code]

while (p_gamesys->getGameWindow()->pollEvent(p_gamesys->getGameEvents())){
[...]
}


the compiler does not complain about the getGameWindow() function, but does complain about the getGameEvents(). why would that happen??

thanks everyone for the help so far!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class GameSys{
    sf::RenderWindow game_window;
    sf::Event game_events;

    public:
    sf::RenderWindow& getGameWindow();
    sf::Event& getGameEvents();
};
sf::RenderWindow& GameSys::getGameWindow(){
    return game_window;
}
sf::Event& GameSys::getGameEvents(){
    return game_events;
}

[some other code]

while (p_gamesys->getGameWindow().pollEvent(p_gamesys->getGameEvents())){
[...]
}

Last edited on
i understand what you say. that is because the code isn't complete, it's simplified. but i need the game_event object outside the runGame() function also.

That sounds like a design flaw to me. As I indicated earlier, you only store one event. runGame processes (potentially) many events, and the only event that will be accessible via GameSys::getGameEvent will be the very last event processed by runGame. All the events processed prior to the last one will be lost.



the compiler does not complain about the getGameWindow() function, but does complain about the getGameEvents(). why would that happen??

As mentioned upthread, sf::Window::pollEvent does not take a pointer.
pollEvent(*(p_gamesys->getGameEvents()))
oh, i understand now. i'll have to make some tests on that later, as i don't know exactly how the sf::Event stores the events...

i think i'll make it the way LowestOne suggested, for now.

thanks everyone for the help. :)
Topic archived. No new replies allowed.