我正在为一个用C ++编写的游戏设计一个抽象的particle类。每个派生的粒子类将具有该类的所有实例使用的不同纹理。当然,我想使用静态成员来存储纹理。但是,每个粒子都会加载,卸载和绘制相同的纹理。因此,我还想在基础粒子类中编写这些函数,而不是为每个派生类重写它们。问题是在C ++中无法创建静态的虚拟成员。
我在相关的Stack Overflow问题(here,here和here)上找到了一些建议。两个常见的建议如下:
texture
),该方法返回对纹理对象的引用,并在每个派生类中重写该方法。这些都是很好的解决方案,但对我来说似乎都不是很理想。
我不能使用(2)因为派生类不共享公共基类,所以我不能使用多态来存储指向不同派生粒子混合的指针。因此,对于我想要添加到场景中的每种类型的粒子,我需要一个单独的容器,这是不可维护的。
选项(1)适用于draw
函数。但正如问题标题所暗示的那样,我没有一个实例变量可以用texture
和load
方法调用unload
。这些方法应该是静态的。这两个函数都是单行的,因此为每个子类编写这两个函数并不困难。但是,它的安全性稍微不那么安全,因为没有任何东西迫使我实现这些功能,即使每个子类都需要它们。另外,我想知道是否有更好的解决方案,以防我或其他人遇到这个问题,使用更复杂的方法(需要更多代码重复)的类层次结构。
可能没有更好的解决方案,但我想我会问这里是否有人可以想到一个,或者解释一下如何改进我的设计以避免这个问题。
编辑:这是选项(1)的示例实现,因为Kerrek SB指出我的问题是缺少代码。
class BaseParticle
{
public:
// Cannot declare virtual load and unload methods because they're static.
void draw()
{
texture().draw();
}
protected:
virtual Texture& texture() = 0;
};
class DerivedParticle : public BaseParticle
{
public:
static void load() // Need to reimplement for every other derived class.
{
_texture.load();
}
static void unload() // Need to reimplement for every other derived class.
{
_texture.unload();
}
private:
static Texture _texture; // Need to create for every derived class.
virtual Texture& texture() { return _texture; }
};
希望我的例子和评论能让问题更加清晰。我基本上试图避免每个静态方法强加的样板代码。
答案 0 :(得分:0)
首先,我建议沿RAII行重构Texture类,以便在构造函数中执行纹理加载,并在析构函数中执行卸载。
然后你就可以静态初始化纹理了。在DerivedParticle的实现(.cpp)文件中,您可以输入:
static Texture DerivedParticle::texture_("derivedtexturefilename");
之后,派生粒子在静态初始化期间获得正确的纹理,并且不需要首先调用加载/卸载方法 - 这更好,因为您可以避免使用未初始化纹理或忘记使用卸载一个。
这假设纹理文件名在编译时是已知的,并且纹理与其他静态对象的初始化顺序并不重要。如果没有,那么你可以通过将静态实例包装在函数中来推迟初始化静态实例,并用对此函数的调用替换它的所有用法:
Texture& DerivedParticle::texture_() {
static Texture* texture = new Texture(fileName);
return *texture;
}
另请参阅C ++ FAQ中的How do I prevent the "static initialization order fiasco"?。