c++ - 避免嵌入式目标上的虚函数

标签 c++ templates virtual

我有一个 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();
}

Live demo .

组成

或者,也许您可​​以使用组合而不是继承,将您的 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();
}

Live demo .

更新: 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/

相关文章:

c++ - 为什么在链接到 zlib.lib 时出现错误 LNK2001?

c++ - 具有 VARIANT 返回类型的模板实例化

c++ - 函数模板重载解析,依赖和非依赖参数

c++ - 为什么 C++ 没有虚拟数据成员?

c++ - 在 boost::lambda 中使用 static_cast

c++ - std::allocator_traits::construct with const 指针

C++ 继承获取错误

javascript - 如何通过javascript从模板中获取元素?

c++ - C++11 中的纯虚函数

c++ - 如何在 linux 上创建虚拟 CAN 端口? (C++)