I'm thinking of creating a big new C++ project. The start is easy - just a simple window, maybe SDL2, maybe SFML, maybe even WIN32. Well, what should I take? Wouldn't it be much nicer to use any window I want to? Without changing much code so that other classes are independent of this window?
Said, done! Using a simple window interface, every class knows of something like a window and I'm able to choose between different types. The only requirement is having IWindow as a base class.
class IWindow {
public:
IWindow(std::string title, int posX, int posY, int width, int height);
IWindow getHandle();
void loop();
bool toggleFullscreen();
bool toggleFullscreen(bool fullscreen);
int getWidth();
int getHeight();
int getPosX();
int getPosY();
//And so on ...
};
But now, since I have to use virtual methods, every time my virtual function loop will be called by the game loop. And virtual functions are slower. About 10%, I've read.
Isn't the compiler able to see what my window will be? Of which type it'll be from? Couldn't it see "Jeah, this programmer guy creates an SDL window in this application, so just use it's methods everywhere."? I mean, I'm defining my window during the main loop and it'll never change. It's nothing dynamical. It's predictable.
So is the compiler able to optimize my predictable virtual function calls? These which will be evaluated every game loop cycle? Like in the following passage?
int main(int argc, char* argv[]) {
//Creates a window derived from IWindow
SDL::Window myWindow("Title", 0, 0, 300, 100);
//Storing it as IWindow in a wrapper class
Game myGame(&myWindow);
//Game loop
//myGame.run() calls the window's loop
while (myGame.run()) {
//... doing game stuff
}
}
With a Game class like this:
class Game {
protected:
IWindow* window;
public:
bool run() {
//Calls the window's virtual loop method.
//Will it be optimized? Any way to do so?
this->window->loop();
}
};
It would be nice to hear of your ideas and experiences.
Darth Moon
Does C++ compiler optimize virtual member calls?
Yes, a compiler might be able to de-virtualize virtual function calls if it can determine the concrete type at compile time.
No, a C++ compiler will not be able to de-virtualize all virtual function calls.
And virtual functions are slower. About 10%
Assuming the 10% difference is correct, consider that function call overhead is probably somewhere in magnitude of a few nano seconds. 10% of a few nano seconds is not a lot. You can fit many, many nano seconds in a single iteration of a soft real time simulation like a game.
Isn't the compiler able to see what my window will be?
So is the compiler able to optimize my predictable virtual function calls?
Maybe.
Firstly, call to run must be expanded inline in the context where the pointer is assigned. Otherwise it cannot make any assumptions about the pointed object. In order to be expanded inline, it must be defined in the same translation unit as where the function is called from (except, LTO may be able to lift this requirement).
Furthermore, the compiler must be able to prove that window is not modified at any point during the execution to point another object. This proof may be impossible depending on what your loop looks like, but there is a simple way to make it easy: declare the pointer const.
As for whether your compiler does optimize it... I don't know. But your compiler does, so I suggest directing your question to your compiler (i.e. ask it to compile your program and see what it does).
Let's sum up our comments.
Virtual calls are costly, but if the processor can detect a pattern, their calling cost gets decreased thanks to the predictors inside modern processors.
Now, let's check your code:
int main(int argc, char* argv[]) {
//Creates a window derived from IWindow
SDL::Window myWindow("Title", 0, 0, 300, 100);
//Storing it as IWindow in a wrapper class
Game myGame(&myWindow);
//Game loop
//myGame.run() calls the window's loop
while (myGame.run()) {
//... doing game stuff
}
}
Let's assume Game has a virtual run. In this instance, the compiler knows that myGame is of type Game and can directly put the call to your run function instead of going through the virtual table.
Now you have this in another file:
class Game {
protected:
IWindow* window;
public:
bool run() {
//Calls the window's virtual loop method.
//Will it be optimized? Any way to do so?
this->window->loop();
}
};
Unfortunately, in this case, there is nothing that the compiler can know by just looking at this file, and as such the call to SDL::Window will go through the virtual run coming from IWindow.
Now with lto (link time optimization), the compiler might be able to figure it out and de-virtualize the code, but it will probably not as the number of optimization options will grow with the number of files as well as the number of combinations.
Related
I am currently implementing a small soft, I want this soft work on Mac OS and Window OS, so I want use GLFW for Mac environment and Window API for Windows environment (I know GLFW is cross platform but that's not the point..)
My problem is a design implementation problem:
I have created a windowManager class that keeps an instance of a Window class. This Window keeps an instance of an object that is a PatternWindow, where PatternWindow is an interface. I have an object PatternGLFW3_VULKAN that implements PatternWindow. This PatternGLFW3_VULKAN has a member GLFWwindow * _window, and PatternGLFW3_VULKAN initializes _window with glfwCreateWindow(...).
class Window : public Singleton<Window>
{
public:
somefunction(...)
initializePatternWindow(unique_ptr<PatternWindow>&& patternWindow)
unique_ptr<PatternWindow> getPatternWindow(){return _patternWindow;}
private:
unique_ptr<PatternWindow> _patternWindow;
}
class PatternWindow
{
public:
PatternWindow();
virtual ~PatternWindow();
virtual void initialize() = 0;
virtual void destroy () = 0;
};
class PatternGLFW3_VULKAN : public PatternWindow
{
public:
PatternGLFW3_VULKAN ();
~PatternGLFW3_VULKAN();
virtual void initialize();
virtual void destroy();
const GLFWwindow& getWindow() const {return *_window;}
private:
GLFWwindow * _window;
};
My question is about the getWindow() function in my PatternGLFW3_VULKAN class; how I can create a virtual getWindow() function in my PatternWindow class in order to get my GLFWwindow* window of the PatternGLFW3_VULKAN at run time. If I am on Mac OS environment, I can create a virtual function GLFWwindow& getWindow() in my PatternWindow, but if I run my software in a Window environment, the type GLFWwindow of the virtual function getWindow() of the patternWindow class won't be correct...
How can I do in order to have a virtual getWindow() in PatternWindow my that returns GLFWwindow or a instance the Windows API screen at run time ?
EDIT:
class PatternWindow
{
public:
PatternWindow();
virtual ~PatternWindow();
virtual void initialize() = 0;
virtual void destroy () = 0;
virtual /*UNKNOW TYPE AT THE COMPILATION*/ getWindow() = 0;
};
/*UNKNOW TYPE AT THE COMPILATION*/
is my problem I do not know how to deal with it, for getting a GLFWwindow* when i am in Mac OS and Windows instance for the windows API when I am compiling in the Windows environment..
In the main loop of my software in want something like that
int main(int argc, char** argv)
{
//initialisation of all my managers ans the data ect..
while(!WindowClosed(Window::getPatternWindow()->getWindow()))
{
//DO SOME STUFF
}
}
The pattern you are heading towards can be done, but you might regret it later. I would infer from your setup that you have two overloads of WindowClosed() – one whose parameter is a GLFWwindow, and one whose parameter is a WinAPI type. The former would use GLFW methods to detect if the window is closed, while the latter would use the Windows API. One problem is that one of organization: how many files contain GLFW-specific methods? Maybe you even have a file with both GLFW methods and Win API methods? That's not necessarily wrong, but it could be a pain in the long run. Another problem is that this approach diverges from the traditional object-oriented approach.
Still, let's not force you down one path through lack of knowledge. To make this approach work, you could use the preprocessor and a typedef. If compiling for Mac, you would use a line like typedef PatternGLFW3_VULKAN WindowType;. If compiling for Windows, you'd use a line defining WindowType to be the corresponding Windows type. Choosing between these lines would be accomplished via #ifdef WINDOWS (or whatever condition is most appropriate). Then getWindow() could be declared to return WindowType.
A better approach (which you realized in the comments) is to shift the functionality to the window objects. Instead of function(object), use object.function(). This requires more virtual functions in your interface class, but there is a benefit that you have fewer files that are OS-specific.
class PatternWindow
{
public:
PatternWindow();
virtual ~PatternWindow();
virtual void initialize() = 0;
virtual void destroy () = 0;
virtual bool closed () = 0; // <-- New pure virtual function
};
class PatternGLFW3_VULKAN : public PatternWindow
{
public:
PatternGLFW3_VULKAN ();
~PatternGLFW3_VULKAN();
virtual void initialize();
virtual void destroy();
virtual bool closed(); // <-- OS-specific code is no longer in an extra file
private:
GLFWwindow * _window;
};
Then in your main function, the call would be:
while(!Window::getPatternWindow()->closed())
There is a further step you might consider. (The question appropriately does not have enough details to determine if this is a viable option.) You might not need polymorphism for what you are trying to do. Suppose you were to use the following declaration.
class PatternWindow
{
#ifdef WINDOWS // Or whatever test is appropriate
typedef PatternGLFW3_VULKAN * WindowType;
#else
typedef /* Windows API type */ WindowType;
#endif
public:
PatternWindow();
~PatternWindow();
void initialize();
void destroy ();
bool closed ();
private:
WindowType _window;
};
This interface no longer supports polymorphism. Is that a bad thing? Do you need multiple classes derived from PatternWindow under a single operating system? Perhaps not. Here is a potential implementation file for this class.
#include "PatternWindow.h"
#ifdef WINDOWS // Or whatever test is appropriate
#include "PatternWinAPI.src" // <-- File with an implementation based on Win API
#else
#include "PatternGLFW.src" // <-- File with an implementation based on GLFW
#endif
If you don't like the .src extension, use something else. Just don't make those files look like something to be compiled on their own. Each file would have an implementation appropriate for the API it uses. For example, PatternGLFW.src might contain a function definition like the following.
void PatternWindow::initialize()
{
_window = glfwCreateWindow(...);
// Etc.
}
This eliminates the overhead of polymorphism and does not seem to introduce a coding burden. Also, you don't have to keep track of which files are needed for which operating systems (simpler build setup). The organization of PatternWindow.cpp is uncommon, though.
I am new to Qt, and today I've been trying to adapt my application to work with QFuture to concurrently run some tasks off the main thread.
I have a method which changes the saturation value of a QImage which returns a QPixmap object to be drawn to my QGraphicsView. This all worked fine not using threads, but obviously it is extremely intensive on the main thread so I wanted to move it off.
I read a few articles regarding Threading in Qt, and found that v5 supports a concurrent run functionality, this sounded perfect for my use case as I thought I would just be able to dispatch my functions onto a new thread as in the snippet below:
void MainWindow::on_slideSaturation_valueChanged(int value)
{
QFuture<QPixmap> future = QtConcurrent::run(slider->modifySaturation, value, image);
future.waitForFinished();
image = future.result();
renderImageToCanvas();
modified = true;
}
However I get the error reference to non-static member function must be called.
This error is being called from my Sliders class, I know I haven't declared the method as static, but when I do it causes a whole heap of errors - is there any way I can pass this method to my concurrent call without it being declared as static?
Sliders.h
class Sliders
{
public:
Sliders();
enum Member { RED, GREEN, BLUE, BRIGHTNESS, CONTRAST, HUE, SATURATION, LIGHTNESS };
QPixmap modifySaturation(int, QPixmap);
void setMember(enum Member, int);
int getMember(enum Member);
private:
int m_redValue;
int m_greenValue;
int m_blueValue;
int m_brightnessValue;
int m_contrastValue;
int m_hueValue;
int m_saturationValue;
int m_lightnessValue;
};
You should call QtConcurrent::run like this:
QFuture<QPixmap> future = QtConcurrent::run(slider,
&Sliders::modifySaturation,
value, image);
But I think you are using it wrong anyway. Your on_slideSaturation_valueChanged slot, which I assume to be executed in the main thread, will be blocked until future.waitForFinished() returns.
I have a Class Player like this:
class Player
{
public:
Player();
~Player(void);
Sprite *sprite;
Sprite *rocket;
void draw(int x, int y, SpaceInvaders *system);
}
and in Player.cpp
void Player::draw(int x, int y, SpaceInvaders *system) {
sprite = system->createSprite("data/player.bmp");
sprite->draw(x, y);
}
Player::~Player(void)
{
sprite->destroy();
rocket->destroy();
}
This draw method is called in a while loop in main:
player.draw(int(xPos), 480-32, system);
The game runs fine until I X the window. That's when I get "Access violation reading location 0x00000004" on the first line in the Player::draw method.
I've read that it might be due to passing a null pointer or null reference but I don't know how to fix this.
Would appreciate any help, thanks!
It's most probably because when closing the window, something gets destroyed while draw is called - most probably the system pointer.
In your case, draw should never be called when the user wants to close its window (unless the x calls another function to start a closing process of some sort). The best would be to first validate that system is not NULL or even better, use a shared pointer to ensure it is still valid when being used. Afterwwards, you shoiuld ensure that draw is not called when the window is closing - that should be done when calling the draw function (or above depending on how you've designed your application.
On a side note, unless you have a caching mechanism (and even that is not the best way to do it), you're recreating your sprite everytime it's being drawn. I suggest you keep a member variable and initialize the sprite in the construtor.
So I am semi-new to C++, and completely new to SDL. Most of my conceptual knowledge of OOP comes from Java and PHP. So bear with me.
I am trying to work out some simple design logic with my program / soon to be side-scroller. My problem lies with trying to make my 'screen' layer (screen = SDL_SetVideoMode(...)) accessible to all my other classes; Hero class, background layer, enemies, etc. I have been loosely following some more procedural tutorials, and have been trying to adapt them to a more object oriented approach. Here is a little bit of what I have so far:
main.cpp
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Game Game;
//Load hero
Hero Hero(Game.screen);
//While game is running
while(Game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Draw
Game.DrawBackground();
Hero.drawHero();
//Update
Game.Update();
}
//Clean up
Game.Clean();
return 0;
}
As you can see, I have a Game class, and a Hero class. The Game class is responsible for setting up the initial window, and placing a background. It also updates the screen as you can see.
Now, since my Game class holds the 'screen' property, which is a handle for SDL_SetVideoMode, I am stuck passing this into any other class (ex: Hero Hero(Game.screen);) that needs to update to this screen... say via SDL_BlitSurface.
Now, this works, however I am getting the idea there has GOT to be a more elegant approach. Like possibly keeping that screen handler on the global scope (if possible)?
TLDR / Simple version: What is the best way to go about making my window / screen handler accessible to all my subsequent classes?
I like the way you are doing it.
Though rather than passing the screen reference I would pass a reference to a game itself. Thus each hero object knows which game it belongs too, it can then ask the game object for the screen as required.
The reason I would do this is so that in a few years when your game is a wide and successful product and you convert it for online-play you really need to do no work. The game server will be able to easily support multiple game objects, each game object hosting multiple hero objects. As each hero object wants to draw it asks the game for the screen abd updates the screen (the screen can now very from game object to game object and still work perfectly (as long as they have the same interface).
class Game
{
public:
Game(Screen& screen)
: screen(screen)
{}
virtual ~Game() {}
virtual Screen& screen() { return theGameScreen;}
void update() { /* Draw Screen. Then draw all the heros */ }
private:
friend Hero::Hero(Game&);
friend Hero::~Hero();
void addHero(Hero& newHero) {herosInGame.push_back(&newHero);}
void delHero(Hero& newHeor) {/* Delete Hero from herosInGame */}
// Implementation detail about how a game stores a screen
// I do not have enough context only that a Game should have one
// So theoretically:
Screen& theGameScreen;
std::vector<Hero*> herosInGame;
};
class Hero
{
public:
Hero(Game& game)
: game(game)
{game.addHero(*this);}
virtual ~Hero()
{game.delHero(*this);}
virtual void Draw(Screen& screen) {/* Draw a hero on the screen */}
private:
Game& game;
};
Main.
#include "Game.h"
#include "Hero.h"
int main(int argc, char* argv[])
{
//Init Game
Screen aScreenObject
Game game(aScreenObject);
//Load hero
Hero hero(game); // or create one hero object for each player
//While game is running
while(game.runningState())
{
//Handle Window and Hero inputs
Game.Input();
Hero.userInput();
//Update
Game.update();
}
//Clean up
// Game.Clean(); Don't do this
// This is what the destructor is for.
}
I don't know if it's elegant, but what I do for the side-scrolling game I'm making is to make a show() function in each class than draws to the screen, and passing the screen handle as a parameter. Then whenever I want to draw something to the screen I just do foo.show(screen). The screen handle is in main().
The first, and honestly, easiest solution, is to use a global variable. Yes, yes, yes, everyone says global variables are horrible, but in this situation, it's perfectly fine.
The other solution, which is a bit more work, but can result in somewhat more portable code, is to encapsulate your drawing functions into a single, static class. This way, you can draw to the screen directly without having to pass around a variable, or have to lie awake at night thinking the code review police will get you because you used a global variable. Plus, this can potentially make it easier if you ever decide to port your game to a new library. Some quick and dirty pseudocode:
class Drawing
public:
static void Draw(x, y, sdl_surface graphic, sdl_rect & clip=null);
static void init(sdl_surface & screen);
private:
sdl_surface screen;
void Drawing::Draw(x, y, sdl_surface graphic, sdl_rect & clip=null)
{
sdl_blit(x, y, graphic, clip);
}
void Drawing::init(sdl_surface & screen)
{
this.screen=screen;
}
It sounds like you're looking for a way to implement the Singleton design pattern, where you would have a single Screen object. If you know you're only ever going to have a single Screen object it should work fine.
In this case you would implement a static method on the Game class:
class Game
{
public:
static Game *GetTheSceenObject();
private:
static Screen *theScreen; // details of initialisation ommitted
}
that would return a pointer to the single Screen object.
If there is a possibility that you'll end up using multiple SDL screens, though, it may be worth creating a Draw() method in your Hero class that is responsible for drawing the hero on each of the Screens managed by the Game class by iterating through a list provided by the Game class.
That functionality could be contained in the methods of a common DrawableThingy class that Hero and Enemy are derived from.
Passing Game.screen around is more OO (though it might be better to have a getter function) than having one instance of it that can be accessed from any class, because if you have one global version, you can't have more than one Game.screen at any one time.
However if you know you'll only ever need one in the entire lifetime of the program, you might consider making Game::Screen() a public static function in the Game class that returns a private static member screen. That way, anyone can call Game::Screen() and get the screen.
Example (assuming ScreenType is the type of screen and that you store a pointer to it):
class Game {
public:
static ScreenType* Screen() {
if (!screen)
screen = GetScreenType(args);
return screen;
}
}
private:
// if you don't already know:
// static means only one of this variable exists, *not* one per instance
// so there is only one no matter how many instances you make
// the same applies to static functions, which you don't need an instance to call
static ScreenType* screen;
};
// and somewhere in a .cpp file
ScreenType* Game::screen = NULL;
// and you use it like this
ScreenType* scr = Game::Screen();
// use scr
I was working for a while with different C++ GUI frameworks (e.g. Qt, wxWidgets, also some proprietary) but cannot decide for myself regarding the topic described below.
As discussed in several questions/answers here, direct use of delete this is valid in C++ (as long as you don't dereference this any more), but it is in most cases not good idea.
But in some cases, object invokes its destructor indirectly. This situation specifically often arise in event drive systems (GUI applications come to mind first).
class Kernel {
public:
void Start() {
_window = new Window();
}
void OnCloseButton() {
if (_window) {
_window->Close();
delete _window;
_window = NULL;
}
private:
MyWindow * _window;
};
class MyWindow
{
public:
MyWindow(Kernel & kernel) : _kernel(&kernel) {
Connect(my_button_close_event, this, OnCloseButtonClicked);
}
OnCloseButtonClicked() {
// This call actually calls destructor of this object.
_kernel->OnCloseButton();
// If we access any fields of Window here, we're going to have problems
}
private:
Kernel * _kernel;
};
Notice: I did not try to compile the code - it may have typos or bad practices. But it should illustrate the idea.
So, the question is: Is it OK to do something like in the example above: the handler of the event calls some other function (method of its owner), which indirectly deletes this?
Or should I better make the Kernel class event aware and connect the event from the button directly to the method in the Kernel and then we do not have this situation of indirect call to delete this.
Thanks in advance.
It's possible to do so since the Window instance is created by the Start() method but it's a bad practice in Object Oriented Programming.