2

I am using SFML and have a class like the following:

#include <SFML\Graphics.hpp>

class Overlay
{
public:
    Overlay(int width, int height);
    Overlay(const sf::Texture*);
    Overlay(const sf::Sprite*);

    ~Overlay();

private:
    sf::Texture _texture;
    sf::Image _img;
};

Now the following constructor for Overlay(const sf::Sprite*) is working:

Overlay::Overlay(const sf::Sprite* spr) {    
    int width = spr->getTexture()->getSize().x;
    int height = spr->getTexture()->getSize().y;
    _texture.create(width, height);
    _img.create(width, height, sf::Color::Transparent);
}

However, the following, nested constructors are not:

Overlay::Overlay(int width, int height)
{
    _texture.create(width, height);
    _img.create(width, height, sf::Color::Transparent);
}

Overlay::Overlay(const sf::Texture* tex) {
    sf::Vector2u textureSize = tex->getSize();
    Overlay(textureSize.x, textureSize.y);
}

Overlay::Overlay(const sf::Sprite* spr) {
    Overlay(spr->getTexture());
}

To me it looks, like the two snippets should be doing the same thing if the following is executed:

sf::Sprite image;
Overlay mOverlay(&image);

Although both of them compile just fine, when the second code snippet (nested constructors) is called, _img ends up having a size of 0 and its m_pixels array is empty.

1 Answers1

7

Delegating Constructors.

It sounds like you are looking for a Delegating Constructor.

To use a delegating constructor, it should appear in another constructor's member initializer list, not the constructor's body.

In your second snippet, you are constructing a temporary Overlay object the stack. When the constructor returns, the temporary is destroyed and has no effect.

Try defining the constructor like so:

Overlay::Overlay(const sf::Sprite& spr)
    : Overlay(spr.getTexture())
{
}

A small code review.

Notice how I used a const sf::Sprite& rather than a const sf::Sprite*? Because the case of spr being a nullptr isn't being handled, it makes sense to pass it by reference to ensure it refers to an object. This also clears up any question as to who owns the texture after the constructor is called.

When you do this, you should also consider declaring the constructor with the explicit keyword like so:

class Overlay
{
public:
    explicit Overlay(const sf::Texture&);
    explicit Overlay(const sf::Sprite&);
};

This prevents Textures and Sprites from accidentally being turned into Overlays when passing them around.

Community
  • 1
  • 1
Sean Cline
  • 6,979
  • 1
  • 37
  • 50