【发布时间】:2014-05-25 23:04:52
【问题描述】:
我正在为我用 C++ 编写的游戏设计一个抽象的 particle 类。每个派生的粒子类将具有该类的所有实例使用的不同纹理。自然,我想使用静态成员来存储纹理。但是,对于每个粒子,纹理的加载、卸载和绘制都是相同的。因此,我还想在基本粒子类中编写这些函数,而不是为每个派生类重写它们。问题是在 C++ 中无法创建静态的虚拟成员。
我发现了一些关于 Stack Overflow 相关问题的建议(here、here 和 here)。两个常见的建议如下:
- 在返回纹理对象引用的基类中创建一个虚拟方法(例如
texture),并在每个派生类中覆盖该方法。 - 使用curiously recurring template pattern 允许我从基类方法调用派生类的静态成员。
这些都是很好的解决方案,但对于我的目的来说似乎都不是很理想。
我不能使用 (2),因为派生类不共享一个公共基类,我不能使用多态性来存储指向不同派生粒子的混合的指针。因此,对于要添加到场景中的每种类型的粒子,我都需要一个单独的容器,这不是很容易维护。
选项 (1) 非常适合 draw 函数。但是正如问题标题所暗示的那样,我没有一个实例变量可以用来从load 和unload 方法调用texture。这些方法应该是静态的。这两个函数都是单行的,因此为每个子类编写这两个函数并不难。但是,这种方式不太安全,因为没有什么强迫我实现这些功能,即使每个子类都应该需要它们。另外,我想知道是否有更好的解决方案,以防我或其他人在类层次结构中遇到这个问题,方法更复杂(需要更多代码重复)。
可能没有更好的解决方案,但我想我想问问这里是否有人能想到一个,或者解释一下我可以如何改进我的设计以避免这个问题。
编辑:这是选项 (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; }
};
希望我的示例和 cmets 能让问题更清楚一些。我基本上是在尝试避免每个静态方法强加的样板代码。
【问题讨论】:
-
这么多话。这么少的代码。
-
好点。我添加了选项 (1) 的基本示例实现。
-
一个主要的问题是纹理的加载是否可以找到相关数据并加载它,或者数据是否流式传输,因此必须在流加载的适当点调用以消化以下数据?
-
您能否将纹理的加载推迟到第一次出现相关粒子的实例?
-
你不能让纹理自己初始化吗?为什么 load() 不只是 Texture 的构造函数,而 unload() 不是它的析构函数?
标签: c++ inheritance static member derived-class