NVI (Non-Virtual Interface)와 Template Method 패턴의 차이점은 무엇입니까?C++ : NVI와 템플릿 메서드 패턴의 차이점은 무엇입니까?
그들은 매우 유사하게 보입니다. 그리고 나는 그것들이 기본적으로 동일하다는 것과 그것들이 어떻게 든 더 일반적 인 Template과 미묘하게 다르다는 것을 모두 읽었습니다.
NVI (Non-Virtual Interface)와 Template Method 패턴의 차이점은 무엇입니까?C++ : NVI와 템플릿 메서드 패턴의 차이점은 무엇입니까?
그들은 매우 유사하게 보입니다. 그리고 나는 그것들이 기본적으로 동일하다는 것과 그것들이 어떻게 든 더 일반적 인 Template과 미묘하게 다르다는 것을 모두 읽었습니다.
NVI는 관용구이며, 템플릿 방법은 패턴입니다. NVI는 C++에서 동적 디스패치를 사용하는 템플릿 메소드 패턴의 구현입니다. 동적 인 dispatch를 제거하기 위해 템플릿 metaprogramming을 사용하여 C++로 템플릿 메소드를 생성하는 것도 가능합니다.
패턴은 관용구보다 일반적이며 언어는 패턴을 구현하는 데 다른 관용구를 사용할 수 있습니다.
NVI는 기본적으로 Template Method 패턴의 언어 별 구현이며 실제로 차이점이 없다고 말하고 있습니까? 동일한 결과를 얻기 위해 C++ 템플릿을 어떻게 사용합니까? –
@Robert S. Barnes 지금까지 볼 수있는 것처럼 C++ 템플릿을 템플릿 방법으로 사용하는 분명한 방법은 없습니다. 템플릿 메소드는 '이렇게하고 다른 것을해라.'라고 말하면서, 할 일 중 하나를 위해 펑터를 만들 수 있지만, C++ 템플릿이 제공하는 타입 매개 변수와는 실제 관계가 없습니다. –
나는 아직도 당신이 여기서 의미하는 것을 이해하지 못하고 있다고 생각한다. "동적 인 디스패치를 제거하기 위해 템플릿 메타 프로그래밍을 사용하여 C++로 템플릿 메서드를 만드는 것도 가능합니다." –
앞서 말했듯이, 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
이 전혀 (심지어 개인적으로도) 존재하지 않습니다. 메모리 레이아웃은 이전 버전과 호환됩니다. 바이너리 호환성을 달성했습니다. 여기
, 우리는 한 번에 여러 패턴을 사용 :
+1 "가상 구현 세부 사항"및 ABI 고려 사항. – neuro
+1. 그러나 가상 인터페이스에 대해 별도의 pimpl과 같은 클래스를 만드는 것에 대해서는 동의해야합니다. 가장 분명한 단점은 클래스 수를 두 배로 늘리는 것입니다. 또한 FooImpl이 불투명하지 않은 경우 사람들이 직접 FooImpl을 사용하고 Foo를 건너 뛸 수 있습니다. 그러나 NVI의 요점은 사람들이 가상 구현을 오버라이드 할 수 있기 때문에 불투명하지는 않을 것이므로 FooImpl을 공개적으로 액세스 할 수 있어야합니다. 비록 그것의 단점을 가지고 있지만, 나는 하나의 클래스에서 NVI를 구현하고 공용 가상 기능을 모두 피하는 것이 더 나은 접근이라고 생각합니다. – stinky472
또한 공용 가상 인터페이스를 제공하는 pimpl과 같은 클래스의 특별한 경우를 만드는 것과는 달리 공개 가상 함수를 사용하지 않는 것이 더 쉬운 정책입니다. – stinky472
위키피디아 링크를 참조로 사용하지 않으려 고합니다. 잠금 장치를 사용하면 예외가 발생하기 쉽지 않습니다 ... –