模板或继承

时间:2015-07-24 20:28:02

标签: c++ templates inheritance stl

您更喜欢哪一个:

template <class STRATEGY>
class A
{
  STRATEGY *m_pMyStrategy; // User has to create new strategy class
// class A needs to use traits 
// or some other means to decide if strategy meets the requirements

};

class A
{
  IBaseStrategy *m_pMyStrategy; // User inherits IBaseStrategy class
};

为什么std :: vector选择第一个用于分配器?

1 个答案:

答案 0 :(得分:1)

我们大多数人可能更喜欢(可能更喜欢,当它变得可用时)是使用某种概念,这样我们就可以吃蛋糕并吃它(可以这么说):通过STRATEGY作为模板参数,但也指定STRATEGY需要满足的要求。

您的第二个(基于继承的)版本会导致一个基本问题:虽然它可以很容易地从策略类中指定客户端类所需的接口,但它要求策略类的作者知道该名称。他在撰写战略课时的策略基础。

换句话说,策略类提供正确的接口是不够的 - 它需要从正确的基类继承,以通知编译器它提供特定接口的事实。

这在大型项目中尤其笨拙 - 您需要进行大量的跨项目协调,以确保人们将要求的所有界面都是提前设计和知晓的,因此每个人都会提供策略类知道在定义类时使用什么作为基类。

概念降低了必要的通信级别,因为客户端类可以直接指定它所需的接口,以及满足的任何策略类,而不是要求策略从指定的基类继承以显示它实现特定的接口。可以使用这些要求。如果代码的不同部分中的两个不同的客户端类都想要使用类似的策略,则他们不必首先协调(例如)同意他们将接受的策略的基类的名称 - 相反,每个只是指定它需要的接口,任何满足该接口要求的类都可以用于该角色(即使它的作者从未听说过他们为接口选择的名称,更不用说将它用作基类了)。

目前,模仿具有特征和static_assert等特征的概念可能是我们能做的最好的事情。代码通常是丑陋和笨拙的,但至少它使基本原理正确 - 特别是,它将责任放在正确的位置。

由于“适当地方的责任”部分可能并不清楚,我的意思是编写策略类的人只需负责提供正确的界面,基本上正确猜测以什么名称(例如)客户端类可以选择为他们定义的基类提供指定他们想要的接口。这也意味着客户端和服务器端(或者你喜欢称之为的任何一方)都不仅仅关注功能而不是创造名称,让其他人正确猜出名称。