C++ C++;:NVI和模板方法模式之间的差异?
NVI()和模式之间的区别是什么C++ C++;:NVI和模板方法模式之间的差异?,c++,design-patterns,template-method-pattern,non-virtual-interface,C++,Design Patterns,Template Method Pattern,Non Virtual Interface,NVI()和模式之间的区别是什么 它们看起来非常相似,我读到它们基本上是一样的,但它们有细微的不同,因为模板更一般。NVI是一种习惯用法,模板方法是一种模式。NVI是一种利用C++动态调度的模板方法模式的实现;也可以使用模板元编程来在C++中创建模板方法来消除动态调度。p> 模式比惯用语更一般,语言可能会使用不同的惯用语来实现模式。如前所述,NVI是一种编程惯用语,与一类语言相关。赫伯·萨特(Herb Sutter)和其他人都在推广它,因为它有助于执行合同: 类不变量 函数契约(对传递的参数和
它们看起来非常相似,我读到它们基本上是一样的,但它们有细微的不同,因为模板更一般。NVI是一种习惯用法,模板方法是一种模式。NVI是一种利用C++动态调度的模板方法模式的实现;也可以使用模板元编程来在C++中创建模板方法来消除动态调度。p>
模式比惯用语更一般,语言可能会使用不同的惯用语来实现模式。如前所述,NVI是一种编程惯用语,与一类语言相关。赫伯·萨特(Herb Sutter)和其他人都在推广它,因为它有助于执行合同:
- 类不变量
- 函数契约(对传递的参数和生成的返回值的断言)
- 重复操作(如日志记录)
- 对生成的异常的控制(尽管这是个坏主意;))
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
是一个实现细节。在接口中公开实现细节是个坏主意,因为您可能希望更改它们
此外,实现细节往往会影响二进制兼容性。例如,在类中添加一个新的virtual
方法可能会改变虚拟表的布局(通用实现技术),从而破坏二进制兼容性。在gcc上,如果希望保持兼容性,则需要确保最后添加它(在虚拟机中)
通过使用上面的NVI+Pimpl组合,在公开的类中根本没有virtual
(甚至没有private)。内存布局向后和向前兼容。我们已经实现了二进制兼容性
在这里,我们同时使用几种模式:
- 模板法
- 策略(因为我们可以随意交换指针)
- 工厂(决定我们得到的实现)
虚拟
函数的问题并不严重由于易于使用,它与ABI。FooImpl
不透明的优点是,您将其限制在二进制文件中,因此在向客户交付新版本的二进制文件时不会出现ABI问题。很好,但是NVI与模板方法有何不同?似乎你是说NVI是在某种语言中实现模板方法的一种特定方式?那么你是说NVI基本上是模板方法模式的一种特定语言实现,除此之外没有什么真正的区别?如何使用C++模板来达到同样的结果?@罗伯特·巴尼斯。据我所见,没有一种明显的方法将C++模板作为模板方法。模板方法说,“这样做,然后做其他事情”,同时你可以为一个或另一个事情创建一个函子,与C++模板给你的类型参数没有真正的关系。我猜我仍然不明白你在这里的意思:“也可以使用模板元编程来在C++中创建模板方法来消除动态调度。“通常在模板方法中,有一些非虚拟调用和一些虚拟调用。您可以将template方法放在模板中,或针对模板专门化进行调用,以便在编译时解析调用,但是您不能直接创建模板专门化,这是一种模板方法-您可以从模板方法调用模板专门化,但模板专门化本身不是模板方法。e、 g.模板T fma(ta,tb,tc){返回a+b*c;}
将调用T::operator+的正确专门化或重载。