2014-10-07 6 views
0

저는 C++ Templates : The Complete Guide (Addison Wesley)의 책을 읽고 클래스 템플릿의 전문화에 대해 질문합니다. 어떻게 작동하는지 이해하지만 주어진 예제에서이 기능을 사용할 때 이해하는데 어려움이 있습니다. 다음은 스택 클래스의 일반적인 정의입니다 :템플릿 특수화

#include <vector> 
#include <stdexcept> 

template <typename T> 
class Stack { 
    private: 
    std::vector<T> elems;  // elements 

    public: 
    void push(T const&);  // push element 
    void pop();    // pop element 
    T top() const;   // return top element 
    bool empty() const {  // return whether the stack is empty 
     return elems.empty(); 
    } 
}; 

는 그리고 여기에

#include <deque> 
#include <string> 
#include <stdexcept> 
#include "stack1.hpp" 

template<> 
class Stack<std::string> { 
    private: 
    std::deque<std::string> elems; // elements 

    public: 
    void push(std::string const&); // push element 
    void pop();      // pop element 
    std::string top() const;  // return top element 
    bool empty() const {   // return whether the stack is empty 
     return elems.empty(); 
    } 
}; 

내 문제는 그것이 캡슐화에 대해 OOP 원칙을 깰 것이다 전문화이다. 클라이언트가 다른 헤더 파일에 두 개의 정의가 있다는 것을 알아야하고 Stack 클래스에 주어진 유형 T를 기반으로 포함시킬 정의가 무엇인지 알아야합니까? 이 시나리오에서는 하나의 일반 Stack 클래스와 특수 StackString 클래스에 대해 두 개의 다른 클래스를 구현하는 것이 낫다.

생각하십니까?

+6

일반적으로 전문화는 동일한 헤더에 포함됩니다. 사용자는 전문화를 사용하고 있다는 것을 알 필요가 없습니다. – juanchopanza

+0

@juanchopanza _ "사용자는 전문화를 사용하고 있다는 것을 알 필요가 없습니다."_ 인터페이스의 동작이 특수화 (물론 잘못된 것으로 간주 됨)에 의해 변경되지 않는 한 똑같은 말을하려고했습니다. –

+0

'Stack'이 정의 된 파일을 수정할 수없는 경우, 다른 파일을 만들고,'MyStack.h'를 만들고, 그 파일에 특성화를 추가하십시오 .' Stack.h' 대신'#include'MyStack.h'을 반드시 사용해야합니다. –

답변

1

클라이언트는 다른 헤더 파일에 에 어쩌면,이 정의가 있다는 것을 알고, 다음 에 따라 포함되는 하나의 알 필요가 Stack 클래스에 주어진 타입 T?

두 개의 서로 다른 개방 헤더, 라이브러리의 사용자가보고 사용할 즉 헤더에 넣어 절대적으로 필요가 없습니다. 내부적으로 두 개의 서로 다른 구현 헤더로 구성 될 수 있으며, 두 가지 구현 헤더는 사용자가보고 포함 할 주요 헤더에 포함됩니다. 그러나 사용자는 이며 명시 적 전문화인지 또는 인지인지 여부를 알지 못합니다. 그것이 가장 확실하게 사용자가해야 이유가 존재하는 대부분의 경우, 전문화가 아직 문서화됩니다

// Stack.impl.hpp 

// primary template: 
template <typename T> 
class Stack { 
    // [...] 
}; 

// Stack_StringSpec.impl.hpp 

#include "Stack.impl.hpp" 
// explicit specialization: 
template <> 
class Stack<std::string> { 
    // [...] 
}; 

// Stack.hpp 

#include "Stack.impl.hpp" // Included for clarity 
#include "Stack_StringSpec.impl.hpp" 

주/인식 할 필요가있다. (예를 들어 std::vector<bool>을 가져 가라.)

+0

이것이 실제로 어떻게 이루어 집니까? 열린 헤더 파일이란 무엇입니까? 이것은 내가 찾고있는 대답처럼 느껴지지만 나는 완전히 따르지 않습니다. –

+0

@ Q-bertsuit 답을 수정했습니다. – Columbo

0

특수한 클래스 주에만 기본 이름을 특화되지 않은 변종으로, 참으로 당신은 인터페이스와 구현 모두, 아니 이전 코드를 재사용 할 수 없습니다 완전히 재 작성해야합니다.

가장 인기있는 전문화는 std::vector<bool>입니다. bool 유형은 1 바이트를 차지하지만 실제로는 1 바이트가 8 개의 bool을 저장할 수 있습니다. bool 배열이 필요할 때 메모리 소비를 줄이기 위해 더 많은 바이트를 단일 바이트로 묶는 것이 합리적 일 것입니다. 여기에서 전문화하면 정확히 달성 할 수 있습니다.

사용자에게 모든 것은 투명합니다. vector<bool>을 정확하게 사용하면 vector<int>이지만, 두 번째는 동적 배열 인 int에 의존하지만 첫 번째 비트는 완전히 다른 방식으로 비트와 함께 재생됩니다.

특수화는 반드시 동일한 머리글에있을 필요는 없지만 사용자가 클래스를 포함 할 때 모든 전문화를 표시하려면주의를 기울여야합니다. 그렇지 않으면 사용하지 못할 수도 있습니다. vector<bool>을 사용할 때 다른 파일을 포함해야 함).