SFML community forums

Help => Window => Topic started by: Dada on July 01, 2013, 04:33:45 pm

Title: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Dada on July 01, 2013, 04:33:45 pm
My problem is already solved but I thought I'd post it with the solution since I hadn't found anything on the topic when I did a search earlier.

I have a class derived from Window that overrides the onCreate function:

class MainWindow: public sf::Window
{
public:
    MainWindow();

protected:
    virtual void onCreate();
};

My original implementation of MainWindow's constructor looked like this:

MainWindow::MainWindow():
        sf::Window(sf::VideoMode(640, 480, 32), "SFML Window")
{
}

However my onCreate wasn't getting called. The reason is that virtual functions are not "in effect" until the instance is done initializing, which happens exactly at the opening { of the most derived constructor.

So the simple fix is this:

MainWindow::MainWindow()
{
    create(sf::::VideoMode(640, 480, 32), "SFML Window");
}

The Window sub-object is initialized with its default constructor first. That finishes the initialization of the complete object. Only then is the create function called, which calls the intended version of onCreate.

Hope that helps someone!
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Nexus on July 01, 2013, 04:37:55 pm
This is not a fix.

Calling virtual functions in the constructor is undefined behavior, independently of whether they are called in the initializer list or the body.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: FRex on July 01, 2013, 04:40:27 pm
Quote
Calling virtual functions in the constructor is undefined behavior, independently of whether they are called in the initializer list or the body.
Is it really? :o http://www.stroustrup.com/bs_faq2.html#vcall

Anyway, Laurent 'forbid' ;D using the onXXX functions in Window because they are undocumented and implementation detail, not meant for users.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Laurent on July 01, 2013, 04:48:02 pm
Quote
Calling virtual functions in the constructor is undefined behavior, independently of whether they are called in the initializer list or the body.
I couldn't find a source mentioning a virtual call from the constructor of the derived class, the examples always do the call from the base class. I even found a source mentioning that the call would not go further than the currently constructed class -- which would be ok in this case.

I'm a little worried because I do the same thing in sf::RenderWindow ;D
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: FRex on July 01, 2013, 05:25:07 pm
(http://oi40.tinypic.com/33zbigo.jpg)
Too funny of a coincidence to pass up.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Dada on July 02, 2013, 01:25:13 am
The behavior is well defined, it just happens to be a little tricky and it tripped me up for a minute. That's why I posted about it.

As for onCreate being off-limits: I saw it in the docs and wanted to use it so... Y'all try and stop me  ;).
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Nexus on July 02, 2013, 07:52:00 pm
Ah you're right. In the constructor (or destructor), only pure virtual function calls from abstract classes or qualified calls to functions derived classes are undefined.

For completeness, here are the corresponding standard paragraphs (from n3337):
Quote from: §12.7/4
Member functions, including virtual functions (10.3), can be called during construction or destruction (12.6.2).
When a virtual function is called directly or indirectly from a constructor or from a destructor, including
during the construction or destruction of the class’s non-static data members, and the object to which the
call applies is the object (call it x) under construction or destruction, the function called is the final overrider
in the constructor’s or destructor’s class and not one overriding it in a more-derived class. If the virtual
function call uses an explicit class member access (5.2.5) and the object expression refers to the complete
object of x or one of that object’s base class subobjects but not x or one of its base class subobjects, the
behavior is undefined.
Quote from: §10.4/6
Member functions can be called from a constructor (or destructor) of an abstract class; the effect of making a
virtual call (10.3) to a pure virtual function directly or indirectly for the object being created (or destroyed)
from such a constructor (or destructor) is undefined.

Nevertheless, the way how SFML uses onCreate() is questionable. sf::Window calls this virtual function during create() or its constructor -- if it is called in the constructor, only the base class version sf::Window::onCreate() will be invoked, which leads to the problem seen here.

There is another design problem: Classes that derive indirectly from sf::Window (for example by deriving from sf::RenderWindow) and override onCreate(), will prevent the function in the middle class from being called. This case happens probably rarely, because users are not supposed to inherit sf::Window indirectly.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Laurent on July 02, 2013, 08:10:39 pm
I should really add to the documentation that these functions are for internal use only.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Nexus on July 02, 2013, 08:31:05 pm
Or don't document them at all; after all, it's the documentation of the public API ;)
(you can at least hide the comments for doxygen, using @internal or just plain // comments)

But isn't it also a problem for SFML itself? If a RenderWindow instance is created using the constructor, how will RenderWindow::onCreate() be called?
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Laurent on July 02, 2013, 09:02:45 pm
Quote
But isn't it also a problem for SFML itself? If a RenderWindow instance is created using the constructor, how will RenderWindow::onCreate() be called?
It is called from the constructor of RenderWindow, not Window. So RenderWindow::onCreate can be reached.
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: FRex on July 02, 2013, 10:10:08 pm
Again this. :P
http://en.sfml-dev.org/forums/index.php?topic=10077.msg69213#msg69213
Title: Re: [SOLVED] Window::onCreate not getting called in my derived class
Post by: Laurent on July 02, 2013, 10:35:40 pm
He he :P