Initialize “inherited static members” in derived class without instance variable
我正在设计一个抽象的粒子类,用于我在C++中写的一个游戏。每个派生的粒子类将具有该类的所有实例使用的不同纹理。当然,我想使用静态成员来存储纹理。但是,每个粒子的纹理加载、卸载和绘制都是相同的。因此,我也希望在基本粒子类中编写这些函数,而不是为每个派生类重写它们。问题是C++无法创建静态的、虚拟的成员。
我发现了一些关于相关堆栈溢出问题的建议(这里、这里和这里)。两种常见的建议如下:
这两个都是很好的解决方案,但对于我来说都不太理想。
我不能使用(2),因为派生类不共享公共的基类,所以我不能使用多态性来存储指向不同派生粒子混合物的指针。因此,我需要一个单独的容器来容纳我想要添加到场景中的每种类型的粒子,这不是很容易维护的。
选项(1)完全适用于
可能没有更好的解决方案,但我想我会问这里是否有人能想到一个解决方案,或者解释如何改进我的设计以避免这个问题。
编辑:这里是选项(1)的一个示例实现,因为Kerrek SB指出我的问题是缺少代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | 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; } }; |
希望我的例子和评论能让问题更清楚一些。我基本上是想避免每个静态方法强加的样板代码。
首先,我建议沿着raii行重新构造纹理类,以便在构造函数中执行纹理加载,并在析构函数中执行卸载。
然后您就可以静态初始化纹理了。在派生粒子的实现(.cpp)文件中,您将放置:
1 | static Texture DerivedParticle::texture_("derivedtexturefilename"); |
之后,派生粒子在静态初始化期间得到正确的纹理加载,并且首先不需要调用加载/卸载方法——这甚至更好,因为您避免了使用未初始化纹理或忘记卸载纹理的可能性。
这假定纹理文件名在编译时是已知的,并且纹理与其他静态对象的初始化顺序也不重要。如果不是这样,则可以通过将静态实例包装在函数中并用对该函数的调用替换它的所有使用来延迟初始化该实例:
1 2 3 4 | Texture& DerivedParticle::texture_() { static Texture* texture = new Texture(fileName); return *texture; } |
另请参见如何防止"静态初始化顺序失败"?在C++ FAQ中。
顺便说一句,最好不要使用带前导下划线的标识符。