[英]Template specializations
我正在阅读Addison Wesley撰写的《 C ++模板:完整指南》一书,对类模板的专业化有疑问。 我了解它是如何工作的,但是我无法从给定的示例中了解何时使用此功能。 这是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类)会更好。
思考?
客户是否需要知道有两个定义(可能位于不同的头文件中),然后根据赋予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>
为例。)
专门的类仅与未专门化的变体共享基本名称,实际上您必须完全重写接口和实现,没有任何以前的代码可以重用。
最受欢迎的专业是std::vector<bool>
。 bool
类型需要1个字节,但实际上一个字节可以存储8个bool
。 当您需要布尔数组时,为了减少内存消耗,将更多的布尔数组打包在一个字节中似乎是合理的。 这里的专业化可以实现这一点。
对用户而言,所有事情都是透明的:您使用vector<bool>
与vector<int>
vector<bool>
完全相同,但是第二个依赖于整数的动态数组,而第一个则以完全不同的方式使用位。
专业化不必一定在同一标头中,但是当用户包括该类时,应该使所有专业化可见,否则您可能会无法使用它们(您不想记住要包括使用vector<bool>
时的另一个文件)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.