2014-10-07 213 views
0

我正在读这本书C++模板:Addison Wesley的完整指南,并且有关于类模板专业化的问题。我明白它是如何工作的,但我很难理解何时使用这个特性。下面是一个Stack类的一般定义:模板专业化

#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 2014-10-07 19:23:31

+0

@juanchopanza _“用户不需要知道他们正在使用专业化。“_我只是想说同样的事情,+除非接口的行为被特殊化改变(当然这被认为是错误的) – 2014-10-07 19:26:10

+0

如果你不能修改定义了'Stack'的文件,创建另一个文件,比如'MyStack.h',并在该文件中添加专门化。确保#include''MyStack.h'而不是'Stack.h'。 – 2014-10-07 19:26:53

回答

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

这将如何在实践中完成?什么是开放的头文件?这感觉就像我正在寻找的答案,但我并没有完全遵循。 – 2014-10-07 19:33:11

+0

@ Q-bertsuit编辑答案。 – Columbo 2014-10-07 19:57:00

0

一个专门类股的基本名称与非专业化的变种,你确实必须完全改写这两个接口和实现,没有以前的代码可重用。

最受欢迎的专业是std::vector<bool>bool类型需要1个字节,但实际上一个字节可以存储8个bools。当你需要一个布尔数组时,为了减少内存消耗,在单个字节中打包更多的数据似乎是合理的。这里的专业化可以实现这一点。

对用户来说,一切都是透明的:使用vector<bool>vector<int>完全一样,但第二个依赖于int的动态数组,第一个以完全不同的方式使用位。

专业化不一定需要在同一个标​​题中,但应该是你的照顾,使所有的专业化,当用户包括类时可见,否则他可能无法使用它们(你不想记住在使用vector<bool>时要包含另一个文件)。