我遇到了一个C ++设计问题,可以在虚函数,模板和分支之间进行选择。这三种实现如下所列。我最终选择了第二种实现方式,它看起来很棘手,但在低延迟设计方面具有最佳性能。
虚拟功能实施:
class Channel : public BaseChannel
{
void packet(...) { for (...) message(...); }
virtual void message(...)=0;
};
class ChannelA : public Channel
{
struct Header {...}
void message(...) { ... }
}
class ChannelB : public Channel
{
struct Header {...}
void message(...) { ... }
}
模板实施:
template <typename TImpl>
class Channel : public BaseChannel
{
void packet(...) { for (...) message(...); }
void message(...);
};
class ChannelA : public Channel<ChannelA>
{
struct Header {...}
void message(...) { ... }
}
class ChannelB : public Channel<ChannelB>
{
struct Header {...}
void message(...) { ... }
}
template <typename TImpl>
inline void Channel<TImpl>::message(...) { static_cast<TImpl*>(this)->message(); }
分支机构实施:
class Channel : public BaseChannel
{
void packet(...) { for (...) message(...); }
struct HeaderA {...}
struct HeaderB {...}
void message(...)
{
if (isHeaderA(...)) messageA(...);
else if (isHeaderB(...)) messageB(...);
}
void messageA(...) { ... }
void messageB(...) { ... }
};
答案 0 :(得分:2)
虚拟主义有自己的开销(虽然是最小的),尽管有一个例外,编译器可以应用优化虚拟调度来编译时间评估,如果可以的话。这就像把它留给编译器的想法。
如果您可以通过CRTP实现相同的多态行为,那么您应该使用模板为您提供慷慨的优势。
所以是的第二种方法是要走的路。
答案 1 :(得分:0)
您的预期剂量是多少?
多态性 - 易于扩展对象,支持不同的对象,你不会遇到抛物线if语句,但你需要做更多的编码和设计,而且很难理解一个谁不具备OO概念或设计模式概念。
模板 - 这似乎是(3)中的分支实现,因为您需要单独存储一个对象。
分支 - 基本且易于编码,但是当您扩展这些对象时会很痛苦,例如,当您拥有OjbectA-ObjcetJ时代码应该如何。嗯,这是抛物线的对象:)
(1)和(3)都需要运行时性能开销,并且(1)具有比(3)更好的性能,因为我已经完成了实验。 (2)会使你的程序更大,就像(3)。
总之,您可以选择(1)您是否有不同的派生类或将来可能会增加,或者您想要您的表现,但您可以选择(3)如果您没有太多的反对意见派生,或者你不需要一个好的表现,或者你不想做更多的编码。