为啥不抽象政策?

Posted

技术标签:

【中文标题】为啥不抽象政策?【英文标题】:Why not abstract policies?为什么不抽象政策? 【发布时间】:2012-03-10 02:08:44 【问题描述】:

在实施政策时,需要遵循特定的界面。据我了解,这些政策必须能够相互替代。在现代 c++ 书中,Ch 1.5 3 策略具有相同的接口“T* Create() ”。为什么不需要抽象它。如果策略应该有许多接口,这将是很重要的。据我了解,抽象类给出了哪些接口应该在具体类(策略类)中的方法。在Wikipedia example“using”中定义了策略应该有哪些接口,但它不是通过抽象类。抽象类的目的不是确保派生类具有所需的接口吗?

我错过了什么?

【问题讨论】:

【参考方案1】:

不同之处在于使用抽象基类的接口具有提供运行时多态性的虚函数。

这些策略用于为模板提供编译时多态性。编译器会注意到您的策略类是否有T* Create()。如果没有,在尝试使用时会出现编译时错误。

【讨论】:

【参考方案2】:

我从未在实践中真正使用过基于策略的设计,而且自从我用 C++ 编写代码以来,它已经很长时间了,但这是我的解释。正如您所指出的,主机类可以通过接口或通过类似 wiki 示例描述的 using output_policy::Print; 之类的方式对使用的策略实施约束。

using 方法的一个优点(或不同之处)是它的主动限制较少且不那么严格,因为策略具有隐含的契约,该契约直接由使用它们的代码表示。在使用示例中,给定代码的当前状态,output_policy 实现只需要实现一个名为 Print 的方法,该方法返回任何内容并接受 language_policy::Message() 返回的任何内容(在这种情况下,所有 language_policies 返回一个 std::string) .这更接近于鸭子打字。

一个缺点是,一旦代码消失,隐含的合同就会消失。另一个缺点是策略之间存在一定程度的依赖关系。作为一个非常人为的例子,如果一个 output_policy 有一个只打印字符串的非泛型 Print 方法,它就不能与只打印整数的 language_policy 一起使用。

我不明白为什么您不能在需要时添加策略接口。一个示例是 HelloWorld 类可能想要约束 output_policy 以便它打印字符串而不是其他任何内容。您可以通过编写如下代码来实现这一点 - 请注意,您必须使用 SFINAE 来强制 output_policy<std::string> 实际实现 OutputPolicyInterface<std::string>

template<typename message_type>
class OutputPolicyInterface

    virtual void Print( message_type message ) = 0;
;


template <template<class> class output_policy, typename language_policy>
class HelloWorld : public output_policy<std::string>, public language_policy


public:
    void Run()
    
        Print( Message() );
        //Print(2);  won't work anymore
    
;

【讨论】:

以上是关于为啥不抽象政策?的主要内容,如果未能解决你的问题,请参考以下文章

为啥套接字连接的基本抽象并不常见?

不明白为啥这个类被认为是抽象类

为啥带有抽象的 agda 不删除某些子句?

为啥要给“抽象:真实”状态一个 url?

为啥要将 Java 接口方法声明为抽象的?

为啥 C# 接口方法没有声明为抽象或虚拟的?