代码之家  ›  专栏  ›  技术社区  ›  Robert S. Barnes Antoni

C++:NVI与模板方法模式的区别?

  •  7
  • Robert S. Barnes Antoni  · 技术社区  · 14 年前

    NVI和NVI有什么区别( Non-Virtual Interface Template Method 模式?

    它们看起来非常相似,我读到它们基本上是一样的,而且它们微妙地不同,因为模板更一般。

    2 回复  |  直到 8 年前
        1
  •  15
  •   Pete Kirkham    14 年前

    NVI是一种习惯用法,模板方法是一种模式。NVI是一种利用C++动态调度的模板方法模式的实现;也可以使用模板元编程来在C++中创建模板方法来消除动态调度。

    一个模式比一个习语更通用,语言可以使用不同的习语来实现这个模式。

        2
  •  11
  •   Matthieu M.    14 年前

    如前所述,NVI是一种编程习语,与一类语言有关。Herb Sutter和其他人都在推广它,因为它有助于执行合同:

    • 函数契约(对传递的参数和生成的返回值的断言)
    • 重复操作(如日志记录)

    然而,实现实际上可能有很大不同,例如,NVI实现的另一个示例是将其与Pimpl结合:

    class FooImpl;
    
    class Foo
    {
    public:
      enum type { Type1, Type2 };
    
      Foo(type t, int i, int j);
    
      int GetResult() const;
    
    private:
      FooImpl* mImpl;
    };
    

    struct FooImpl
    {
      virtual ~FooImpl();
      virtual int GetResult() const;
    };
    
    class FooType1: public FooImpl
    {
    public:
      FooType1(int i, int j);
      virtual int GetResult() const;
    private:
      /// ...
    };
    

    我总是发现它更好地表达了这一点。你弄明白了吗?

    virtual 是一个实现细节。在接口中公开实现细节是个坏主意,因为您可能希望更改它们。

    类中的方法可能会改变虚拟表的布局(通用实现技术),从而破坏二进制兼容性。在gcc上,如果希望保持兼容性,您需要确保最后添加它(在虚拟机中)。

    通过使用上面的NVI+Pimpl组合,没有 在课堂上(甚至不是私人的)暴露。内存布局前后兼容。我们已经实现了二进制兼容。

    在这里,我们同时使用几种模式:

    • 工厂(决定我们得到哪个实现)