在 sfml 中为派生 类 初始化一次纹理

Initialize texture once for derived classes in sfml

最近,我尝试用纹理练习 SFML。但是,我遇到了一些问题。 SFML 网站告诉我,使用纹理最有效的方法是更新精灵。否则,我们的程序可能会消耗大量内存。我有一个基础 class 和另外两个 class 派生自它。我如何初始化我的 texture 变量,以便派生的 classes 可以将它用于他们的精灵?我已经尝试在 Base class 构造函数中初始化纹理并在派生的 classes 中调用它,但是后来,我意识到我的问题没有解决,因为调用一个构造函数两次是一个废话。这个问题对我来说非常重要,因为我正在使用创建大量动态分配对象的状态模式。

#include <iostream>

class Base
{
protected:
    sf::Texture texture; //How to initialize this?
    sf::Sprite sprite;
public:
    Base();
};

class Derived1 : public Base
{
public:
    Derived1()
    {
        sprite.setTexture(texture);
    }
};

class Derived2 : public Base
{
public:
    Derived2()
    {
        sprite.setTexture(texture);
    }
};

享元模式

SFML website tells me that the most efficient way to use textures is to update sprites. Otherwise, our program may consume a lot of memory.

是的,sf::Spritesf::Texture的关系对应的是The Flyweight Pattern,一种结构化设计模式。

sf::Texture 是一种重量级 对象,我们希望尽可能共享其数据以节省内存。一个sf::Sprite是一个享元对象,多个sf::Sprite对象可以引用同一个sf::Texture对象来共享它的数据。

sf::Sprite 只包含特定于它所引用的纹理的特定用途的信息,例如纹理的位置、旋转、大小——这是 外部的状态sf::Texture 对象包含可以由多个 sf::Sprite 对象共享的数据(即纹理图像本身)——这是由所有对象共享的 内在状态 引用相同 sf::Texture.

sf::Sprite 个对象

在 SFML 库中,您还可以找到带有 sf::Text/sf::Fontsf::Sound/sf::SoundBuffer 的这种模式。


不放弃享元

牢记上面公开的模式,您可能还想在设计中遵循它:

class Base {
public:
    Base(const sf::Texture& texture): sprite(texture) {}
protected:
    sf::Sprite sprite;
};

class Derived: public Base {
public:
    Derived(const sf::Texture& texture): Base(texture) {}
    // ...
};

sprite数据成员通过sf::Texture初始化,通过引用传递给构造函数,多个BaseDerived对象可以共享同一个sf::Texture.

举个例子:

sf::Texture myTexture;
myTexture.loadFromFile("myImageFile.png");

Base b1(myTexture), b2(myTexture);
Derived d1(myTexture), d2(myTexture);

b1b2d1d2 都共享同一个 sf::Texture 实例 – myTexture:

当然,none 这些对象的寿命应该比 myTexture 长。