Dyamic与C++中的静态多态性:哪个更好?

vid*_*vid 18 c++ polymorphism optimization static-polymorphism

我知道动态/静态多态性取决于应用程序的设计和要求.但是,如果可能的话,是否建议选择动态静态多态?特别是,我可以在我的应用程序中看到以下2个设计选择,这两个设计似乎都被建议不要:

  1. 使用CRTP实现静态多态性:没有vtable查找开销,同时仍以模板基类的形式提供接口.但是,使用很多开关和static_cast来访问正确的类/方法,这是危险的

  2. 动态多态性:实现接口(纯虚拟类),将查询成本与偶然的简单函数(如访问器/更改器)相关联

我的应用程序非常关键,所以我赞成静态多态.但需要知道使用过多的static_cast是否表明设计不佳,以及如何在不产生延迟的情况下避免使用.

编辑:感谢您的见解.以具体案例为例,哪一种更好?

class IMessage_Type_1
{
  virtual long getQuantity() =0;
...
}
class Message_Type_1_Impl: public IMessage_Type_1
{
  long getQuantity() { return _qty;}
...
}
Run Code Online (Sandbox Code Playgroud)

要么

template <class T>
class TMessage_Type_1
{
  long getQuantity() { return static_cast<T*>(this)->getQuantity(); }
...
}
class Message_Type_1_Impl: public TMessage_Type_1<Message_Type_1_Impl>
{
  long getQuantity() { return _qty; }
...
}
Run Code Online (Sandbox Code Playgroud)

请注意,每个类中都有几个mutators/accessors,我需要在我的应用程序中指定一个接口.在静态多态性中,我只切换一次 - 获取消息类型.但是,在动态多态性中,我使用虚函数进行EACH方法调用.这不是一个使用静态聚合物的情况吗?我相信CRTP中的static_cast非常安全且没有性能损失(编译时限)?

Jam*_*nze 14

静态和动态多态性旨在解决不同的问题,因此很少有两种情况都适合.在这种情况下,动态多态将导致更灵活,更易于管理的设计.但大部分时间,由于其他原因,选择将是显而易见的.

两者的粗略分类:虚函数允许公共接口的不同实现; 模板允许不同的接口用于通用实现.


Emi*_*lia 8

一个开关只不过是一系列跳转 - 在优化之后 - 成为跳转到由表查找的地址.完全像虚函数调用.

如果必须根据类型跳转,则必须先选择类型.如果在编译时无法完成选择(主要是因为它取决于输入),则必须始终执行两个操作:select&jump.您用来选择的语法工具不会改变性能,因为优化相同.

事实上,你正在重塑 v-table.

  • @vid:实际上我们可以讨论两个接口:(i)库和外部调用者之间的接口(客户端接口)(ii)核心库类与其后代之间的接口(扩展器接口).我建议你考虑将这两个接口设计为两个独立的(!)任务 (3认同)
  • @vid:... CRPT可能真的"指定"唯一的前(扩展器)接口(ii)客户端接口(i)的设计取决于将派生类暴露给客户端的可能性.如果这种说明是不可能的(不希望的),那么使用虚函数,就没有办法做得更好. (2认同)

ebo*_*ebo 6

您会看到与纯模板基于多态性相关的设计问题.虽然看起来虚拟基类可以让您非常了解派生类的预期,但在模板化设计中却会变得更加困难.通过在使用其中一个boost库时引入语法错误,可以很容易地证明.

另一方面,您在使用虚拟功能时担心性能问题.证明这将是一个问题要困难得多.

恕我直言,这是一个非问题.坚持使用虚函数,直到另有说明.虚函数调用比大多数人想象的快得多(从动态链接库调用函数也增加了一层间接.似乎没有人想到这一点).

我只会考虑一个模板设计,如果它使代码更易于阅读(通用算法),您使用的已知与虚拟功能(数字算法),或者你已经确定它为一个性能瓶颈慢少数案例之一.