我有一个class Player,它可以回放由大量相等块组成的大内存块中的数据。
typedef char chunk_t[100];
typedef struct {
chunk_t data[100]
} blockOfMemory_t;从理论上讲,播放器本身可以处理不同的布局和数据内容,所以我想以一种可重用的方式对其进行编程。为了做到这一点,我想到了这样的事情:
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;
}通过继承它并在子程序中实现数据细节,我可以实现可重用性。
然而,目标是一个ARM皮质M4处理器和速度是非常重要的。因此,我希望在使用虚拟函数时会出现性能缺陷。因此,我正在寻找一种方法来实现相同类型的可重用性,它可以在编译时解析,并允许chunkHasX(..)的内联,等等。
这是尖叫的“模板”-但我该怎么做呢?
谢谢!
发布于 2015-09-09 15:21:26
我将假设您已经测量并确认了虚拟函数调用或增加对象大小的成本使得这样做是可取的。或者你只是觉得模板设计更好。
用CRTP进行继承
如果要使用继承,可以使用奇怪的是反复出现的模板模式(CRTP)。您有一个模板播放器基类,其中模板参数是派生类:
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的评论提醒我,如果你想从形式上对待这些不同的球员,你可以。只需引入一个接口:
class IPlayer {
public:
virtual ~IPlayer(){}
virtual void play() = 0;
};然后,在这两种情况下,您可以从这个接口继承并覆盖play()函数:
template<class T>
class Player : IPlayer {
public:
void play() override;
};例如,现在可以将播放器放在一个容器中,但是在内部循环中调用虚拟函数不会影响性能。现场演示与CRTP和作文。
发布于 2015-09-09 13:08:04
调用虚拟函数与静态函数的成本在最坏的情况下是一次查找。
每个对象都有一个指向它的vtable的指针,其中包含虚拟函数指针,所以如下所示:
ldr [r0,#8],r4
blx r4而不是
ldr #0x400025e5,r4
blx r4或者(如果您需要分支的地址可以内联编码)
br #0x1035只要您不是在紧循环中调用虚拟函数,它就不是一个问题。
https://stackoverflow.com/questions/32478555
复制相似问题