我有一个 class Player
播放来自由许多相等 block 组成的大内存块的数据。
typedef char chunk_t[100];
typedef struct {
chunk_t data[100]
} blockOfMemory_t;
Player 本身在理论上可以适用于不同的布局和数据内容,因此我想以可重用的方式对其进行编程。为此,我想到了这样的事情:
class Player {
public:
Player() { ... }
virtual ~Player() { ... }
void play()
{
for (int i = 0; i < getNumChunks(); i++)
{
if (chunkHasX(i) || chunkHasY(i))
playChunk(i);
}
}
protected:
virtual int getNumChunks() = 0;
virtual bool chunkHasX(int chunkIndex) = 0;
virtual bool chunkHasY(int chunkIndex) = 0;
virtual void playChunk(int chunkIndex) = 0;
}
通过从中继承并在 child 中实现数据细节,我可以实现可重用性。
但是,目标是 ARM Cortex-M4 处理器,速度非常重要。出于这个原因,我预计在使用虚函数时会出现性能缺陷。所以我正在寻找一种方法来实现相同类型的可重用性,这种方法可以在编译时解决,并允许内联 chunkHasX(..)
等。
这是尖叫的"template"——但我该怎么做呢?
谢谢!
最佳答案
我假设您已经测量并确认虚函数调用的成本或增加的对象大小使得这样做是可取的。或者,也许您只是认为模板设计更可取。
CRTP继承
如果你想使用继承,你可以使用 Curiously recurring template pattern (CRTP) .您有一个模板化的 Player 基类,其中模板参数是派生类:
template<class Derived>
class Player {
public:
void play()
{
auto& derived = static_cast<Derived&>(*this);
for (int i = 0; i < derived.getNumChunks(); i++)
{
if (derived.chunkHasX(i) || derived.chunkHasY(i))
derived.playChunk(i);
}
}
};
class DerivedPlayer : public Player<DerivedPlayer> {
private:
friend class Player<DerivedPlayer>;
int getNumChunks();
bool chunkHasX(int chunkIndex);
bool chunkHasY(int chunkIndex);
void playChunk(int chunkIndex);
};
int main() {
DerivedPlayer p;
p.play();
}
组成
或者,也许您可以使用组合而不是继承,将您的 Player
组合成作为模板参数传递的 ChunkHolder
:
template<class ChunkHolder>
class Player {
private:
ChunkHolder chunk_holder;
public:
void play()
{
for (int i = 0; i < chunk_holder.getNumChunks(); i++)
{
if (chunk_holder.chunkHasX(i) || chunk_holder.chunkHasY(i))
chunk_holder.playChunk(i);
}
}
};
class MyChunkHolder {
public:
int getNumChunks();
bool chunkHasX(int chunkIndex);
bool chunkHasY(int chunkIndex);
void playChunk(int chunkIndex);
};
int main() {
Player<MyChunkHolder> p;
p.play();
}
更新: Russ Schultz 的评论提醒我,如果你想多态地对待这些不同的玩家,你可以。简单介绍一个接口(interface):
class IPlayer {
public:
virtual ~IPlayer(){}
virtual void play() = 0;
};
然后在这两种情况下,您都可以继承此接口(interface)并覆盖 play()
函数:
template<class T>
class Player : IPlayer {
public:
void play() override;
};
例如,现在您可以将播放器放在一个容器中,但您不会通过在内部循环中调用虚函数来降低性能。 使用 CRTP 进行现场演示和 composition .
关于c++ - 避免嵌入式目标上的虚函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32478555/