7

NVI (Non-Virtual Interface)와 Template Method 패턴의 차이점은 무엇입니까?C++ : NVI와 템플릿 메서드 패턴의 차이점은 무엇입니까?

그들은 매우 유사하게 보입니다. 그리고 나는 그것들이 기본적으로 동일하다는 것과 그것들이 어떻게 든 더 일반적 인 Template과 미묘하게 다르다는 것을 모두 읽었습니다.

+1

위키피디아 링크를 참조로 사용하지 않으려 고합니다. 잠금 장치를 사용하면 예외가 발생하기 쉽지 않습니다 ... –

답변

11

NVI는 관용구이며, 템플릿 방법은 패턴입니다. NVI는 C++에서 동적 디스패치를 ​​사용하는 템플릿 메소드 패턴의 구현입니다. 동적 인 dispatch를 제거하기 위해 템플릿 metaprogramming을 사용하여 C++로 템플릿 메소드를 생성하는 것도 가능합니다.

패턴은 관용구보다 일반적이며 언어는 패턴을 구현하는 데 다른 관용구를 사용할 수 있습니다.

+1

NVI는 기본적으로 Template Method 패턴의 언어 별 구현이며 실제로 차이점이 없다고 말하고 있습니까? 동일한 결과를 얻기 위해 C++ 템플릿을 어떻게 사용합니까? –

+0

@Robert S. Barnes 지금까지 볼 수있는 것처럼 C++ 템플릿을 템플릿 방법으로 사용하는 분명한 방법은 없습니다. 템플릿 메소드는 '이렇게하고 다른 것을해라.'라고 말하면서, 할 일 중 하나를 위해 펑터를 만들 수 있지만, C++ 템플릿이 제공하는 타입 매개 변수와는 실제 관계가 없습니다. –

+0

나는 아직도 당신이 여기서 의미하는 것을 이해하지 못하고 있다고 생각한다. "동적 인 디스패치를 ​​제거하기 위해 템플릿 메타 프로그래밍을 사용하여 C++로 템플릿 메서드를 만드는 것도 가능합니다." –

8

앞서 말했듯이, NVI는 언어 범주와 관련된 프로그래밍 이디엄입니다. 이 계약 이행하는 데 도움이 있기 때문에 그것은, 다른 사람의 사이에서 허브 셔터에 의해 추진 된 것 :

  • 클래스 불변을
  • 반복적 인 작업 (로그 기록 등) (전달 된 매개 변수와 생성 된 반환 값 이상 주장)
  • 기능 계약
  • 생성 된 예외 위에
  • 제어 (비록 좋지))

하지만, 실제로 구현 예 NVI의 또 다른 예를 들면, 상당히 다를 수있다

class FooImpl; 

class Foo 
{ 
public: 
    enum type { Type1, Type2 }; 

    Foo(type t, int i, int j); 

    int GetResult() const; 

private: 
    FooImpl* mImpl; 
}; 

그리고 구현 : 구현 Pimpl와 결합하는 것입니다

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이 전혀 (심지어 개인적으로도) 존재하지 않습니다. 메모리 레이아웃은 이전 버전과 호환됩니다. 바이너리 호환성을 달성했습니다. 여기

, 우리는 한 번에 여러 패턴을 사용 :

  • 템플릿 방법
  • 전략을
  • 공장 (우리가 얻을 수있는 구현 결정)
(우리는 의지의 포인터를 교환 할 수 있기 때문에)
+0

+1 "가상 구현 세부 사항"및 ABI 고려 사항. – neuro

+0

+1. 그러나 가상 인터페이스에 대해 별도의 pimpl과 같은 클래스를 만드는 것에 대해서는 동의해야합니다. 가장 분명한 단점은 클래스 수를 두 배로 늘리는 것입니다. 또한 FooImpl이 불투명하지 않은 경우 사람들이 직접 FooImpl을 사용하고 Foo를 건너 뛸 수 있습니다. 그러나 NVI의 요점은 사람들이 가상 구현을 오버라이드 할 수 있기 때문에 불투명하지는 않을 것이므로 FooImpl을 공개적으로 액세스 할 수 있어야합니다. 비록 그것의 단점을 가지고 있지만, 나는 하나의 클래스에서 NVI를 구현하고 공용 가상 기능을 모두 피하는 것이 더 나은 접근이라고 생각합니다. – stinky472

+0

또한 공용 가상 인터페이스를 제공하는 pimpl과 같은 클래스의 특별한 경우를 만드는 것과는 달리 공개 가상 함수를 사용하지 않는 것이 더 쉬운 정책입니다. – stinky472

관련 문제