Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Need help understanding how this code works.  (Read 9236 times)

0 Members and 2 Guests are viewing this topic.

Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Need help understanding how this code works.
« on: August 28, 2012, 12:25:33 pm »
Hi again.  I'm going through the SFML tutorial on github.com named "Manage different screens in a game", which can be found here:
 https://github.com/SFML/SFML/wiki/TutorialScreens
Would appreciate it if someone can explain how the following code works:

// Screen.hpp

class cScreen
{
public :
    virtual int Run (sf::RenderWindow &App) = 0;
};

----------

// Main.cpp

01 #include <fstream>
02 #include <iostream>
03 #include <sfml/Graphics.hpp>
04 #include "screens.hpp"  // Includes screen.hpp, screen_0.hpp and screen_1.hpp
05
06 int main(int argc, char** argv)
07 {
08    //Applications variables
09    std::vector<cScreen*> Screens;
10    int screen = 0;
11
12    //Window creation
13    sf::RenderWindow App(sf::VideoMode(640, 480, 32), "SFML Demo 3");
14
15    //Mouse cursor no more visible
16    App.ShowMouseCursor(false);
17
18    //Screens preparations
19    screen_0 s0;
20    Screens.push_back (&s0);
21    screen_1 s1;
22    Screens.push_back (&s1);
23
24    //Main loop
25    while (screen >= 0)
26    {
27        screen = Screens[screen]->Run(App);
28    }
29
30    return EXIT_SUCCESS;
31 }
 

(For more details on "all" of the code, please refer to the link given.)

Line 09 is:  std::vector<cScreen*> Screens;
I understand that it's instantiating a vector named Screens.  What I don't understand is how the cScreen* pointer type is used.

The class screen_0 inherits from the class cScreen.  Similarly, the class screen_1 inherits from the class cScreen.  But the code in screen_0 is different from the code in screen_1.  So when line-09 instantiates the Screens vector using <cScreen*>, how does the vector know the size of screen_0 and screen_1 since they are both different sizes?

I assume that when screen_0 and screen_1 are push_back'd into the Screens vector, the vector just logs the starting address of each push_back and the actual size of each element is irrelevant.  Is that correct?  If so, then why does the "std::vector<cScreen*> Screens" need to know what type of pointer cScreen is?  If it's just a memory address that's being logged, why care that the pointer type is cScreen?

Learning C++ so please excuse my noobie question,
Raptor
« Last Edit: August 28, 2012, 12:27:53 pm by Raptor88 »

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #1 on: August 28, 2012, 12:41:42 pm »
It's polymorphism, you should look that up.
The vector stores the cScreen pointer so that method Run() can be called, because cScreen objects and their derieved objects have that method.
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need help understanding how this code works.
« Reply #2 on: August 28, 2012, 01:18:23 pm »
The class screen_0 inherits from the class cScreen.  Similarly, the class screen_1 inherits from the class cScreen.  But the code in screen_0 is different from the code in screen_1.  So when line-09 instantiates the Screens vector using <cScreen*>, how does the vector know the size of screen_0 and screen_1 since they are both different sizes?

If so, then why does the "std::vector<cScreen*> Screens" need to know what type of pointer cScreen is?  If it's just a memory address that's being logged, why care that the pointer type is cScreen?
In fact you could declare the vector as std::vector<void*> and then you'd be able to pass in any pointer to any class, but it's not adviced to do so.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #3 on: August 28, 2012, 01:34:07 pm »
I'm not sure but I think bad(and cool  ;D) things happen if you mix void* with polymorhpism like that without many casts:
std::vector<void*> yay;
myclass1 one;//derieved from baseclass which has virtual method ouch()
yay.push_back(&one);//should be static_cast<void*>(static_cast<baseclass*>(&one))
baseclass * ptr =static_cast<baseclass*>(yay[0]);
ptr->ouch();
 
One of last two lines(I think last) would cause extremely interesting error.
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need help understanding how this code works.
« Reply #4 on: August 28, 2012, 01:44:41 pm »
Yeah there are nearly no scenarios where void-pointers would make sense and couldn't be replaced by something else, so just don't use it.
My point was more that the size of the class indeed doesn't matter, since a pointer is just a pointer, with the decleration of which class you can catch access violates and all kinds of messy stuff at compile time.

As for the cast, you could use reinterpret_cast<derived*> but that's also very very bad. :D
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #5 on: August 28, 2012, 01:49:13 pm »
That actually came up in my code while tying something to box2d but could come up when tying box2d and sfml because physical bodies and fixtures(and joints) can hold void* pointer and attempting to cast directly from sprite/text/whatever pointer to void* and then later casting from void* to drawable* and trying to draw it would cause that error.
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need help understanding how this code works.
« Reply #6 on: August 28, 2012, 02:06:03 pm »
Yeah Box2D's classes aren't that nicely designed, specially the void-pointer thing could've been done a bit better, but with that it was way easier to port it to other platforms/languages.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #7 on: August 29, 2012, 06:21:25 am »
It's polymorphism, you should look that up.
The vector stores the cScreen pointer so that method Run() can be called, because cScreen objects and their derieved objects have that method.

FRex,

Thanks for pointing me in the right direction.  I had not gotten to polymorphism yet so had no clue. 

With your gentle nudge, I checked all of my C++ books and found that Deitel's "C++ How to Program" gives a great in-depth explanation of exactly what I was asking, in the polymorphism chapter.  It has example code similar to the code I posted and it has a section that explains how C++ handles it "Under the Hood".

Thanks,
Raptor


Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #8 on: August 29, 2012, 12:06:22 pm »
*** Next question in understanding the code for "Manage different screens in a game". ***
Please refer to this link to see all of the code.  https://github.com/SFML/SFML/wiki/TutorialScreens

The "screen_0.hpp" and "screen_1.hpp" files contain both header and function definitions.  There are no "screen_0.cpp" or "screen_1.cpp" files.  Especially note that "screen_1.hpp" is supposed to hold the actual game itself.  How can all of the code be in the header files?

Do the function definitions "have to reside" in the header files with no .cpp files in order for this concept to work?

Confused,
Raptor

Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #9 on: August 29, 2012, 02:45:16 pm »
*** Error msg when code entered into VC++ Express 2010 ***

I entered all of the code for "Manage different screens in a game" in VC++ Express 2010 setup for SFML 2.0.
I converted the code in all of the files from SFML 1.6 to 2.0.  I got rid of all of the red error markers in all of the files except for one.

The one red error marker left is under the period in line-23 in the code below.

The error message is:
  Error:  No instance of overloaded function "std::vector<_Ty, _Ax>::push_back[with _Ty=cScreen*, _Ax=std::allocator<cScreen*>]" matches the argument list

There's no red marker in line 25.

Why is there a red error marker under the period in line-23 but not in line-25?

Here's the code for Main.cpp:
01 //
02
03 #include "stdafx.h"
04 #include <fstream>
05 #include <iostream>
06 #include <sfml/Graphics.hpp>
07 #include "screens.hpp"
08
09 int _tmain(int argc, _TCHAR* argv[])
10 {
11     //Applications variables
12     std::vector<cScreen*> Screens;
13     int screen = 0;
14
15     //Window creation
16     sf::RenderWindow App(sf::VideoMode(640, 480, 32), "SFML Demo 3");
17
18     //Mouse cursor no more visible
19     App.setMouseCursorVisible(false);
20
21     //Screens preparations
22     screen_0 s0;
23     Screens.push_back (&s0);    //<<< Red error marker under the period in this line.
24     screen_1 s1;
25     Screens.push_back (&s1);   //<<< No red error marker in this line.
26
27     //Main loop
28     while (screen >= 0)
29     {
30         screen = Screens[screen]->Run(App);
31     }
32
33     return EXIT_SUCCESS;
34
35 }
 

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need help understanding how this code works.
« Reply #10 on: August 29, 2012, 05:32:19 pm »
Why is there a red error marker under the period in line-23 but not in line-25?
Please keep in mind that Intellisense (the module that makes those red markings) isn't always a reliable source for error checking, sometimes things can also get marked although they compile fine, just because Intellisense hasn't cached everything right. So don't always trust the markings but look at the compiler/linker errors.

As for your problem, Intellisense only marks the first occuring problem with the same variable. And since you use twice the same vector it only marks the first one.
Although I'm not quite sure why it errors at the push_back, but I'd have to look again closer on what's allowed with polymorphism. ;)

The "screen_0.hpp" and "screen_1.hpp" files contain both header and function definitions.  There are no "screen_0.cpp" or "screen_1.cpp" files.  Especially note that "screen_1.hpp" is supposed to hold the actual game itself.  How can all of the code be in the header files?

Do the function definitions "have to reside" in the header files with no .cpp files in order for this concept to work?
That's just bad/lazy programming from the creator of that (one year old) tutorial. You should always seperate the decleration (in .hpp file) and the definition (in .cpp file). ;)
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

FRex

  • Hero Member
  • *****
  • Posts: 1848
  • Back to C++ gamedev with SFML in May 2023
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #11 on: August 29, 2012, 05:55:00 pm »
Quote
That's just bad/lazy programming from the creator of that (one year old) tutorial. You should always seperate the decleration (in .hpp file) and the definition (in .cpp file).  ;)
Unless you don't have definitions. :D (Only a sith deals in absolutes)

Show us the code you ported to sf 2.0, only thing that comes to mind is that your two screens aren't derieved from that base screen somehow but that'd quite unlikely.
Back to C++ gamedev with SFML in May 2023

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11032
    • View Profile
    • development blog
    • Email
Re: Need help understanding how this code works.
« Reply #12 on: August 29, 2012, 06:00:28 pm »
Unless you don't have definitions. :D (Only a sith deals in absolutes)
Hu? If you don't have any definitions you don't create a .cpp file obviously (there's nothing to split then)... ;)
Also base classes often don't use cpp files although they have some definitions too, but one then uses inline definition. THis is then again subtile and can vary widely from person to person.
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #13 on: August 29, 2012, 10:38:01 pm »
Hi FRex and eXpl0it3r,

I got the "Manage different screens in a game" ported to SFML 2.0 and working.

The reason for the red error flag under the period in "Screens.push_back (&s0);" in Main.cpp, was that there were errors in the screen_0.hpp and screen_1.hpp files. 

I had not tried to compile the project and was only concentrating on trying to get rid of all red error flags in all files before compiling.  Once I clicked the Debug arrow in VC++, I got the compile errors.  After I corrected all of the compile errors in the screen_0.hpp and screen_1.hpp files, then the red error flag in the Main.cpp file went away.

Learned a lesson that red error flags in one file can actually be caused by errors in a different file.

Understand how the code in "Manage different screens in a game" works now, thanks to both of your help.

Thanks!
Raptor

Raptor88

  • Full Member
  • ***
  • Posts: 111
    • View Profile
    • Email
Re: Need help understanding how this code works.
« Reply #14 on: August 29, 2012, 11:37:00 pm »
Opps, forgot to ask another question.  What's the "_INCLUDED" suffix on the pre-processor directives for?  I've looked in all of my C++ books and did a bit of Googling but have not found an explanation for why it's needed.

#ifndef SCREENS_HPP_INCLUDED
#define SCREENS_HPP_INCLUDED

//Basic Screen Class
#include "screen.hpp"

//Including each screen of application
#include "screen_0.hpp"
#include "screen_1.hpp"

#endif // SCREENS_HPP_INCLUDED