2.类模板
书中主要围绕通过一个现有的vector实现一个stack,读者需要关注的就是类成员函数实现时,也需要通过template<class T>来实现,具体代码如下:
#include<iostream>
#include <cstring>
#include <vector>
#include <cassert>
using namespace std;
template <class T>
class mystack
{
public:
void push(T const& elem);
T const& top();
void pop();
bool empty();
void printOn(std::ostream& strm) const
{
for (T const& elem : elementArr)
{
strm << elem <<endl;
}
}
private:
vector<T> elementArr;
};
template<class T>
void mystack<T>::push(T const& elem)
{
elementArr.push_back(elem);
}
template<class T>
T const& mystack<T>::top()
{
assert(!elementArr.empty());
return elementArr.back();
}
template<class T>
void mystack<T>::pop()
{
assert(!elementArr.empty());
elementArr.pop_back();
}
template<class T>
bool mystack<T>::empty()
{
return elementArr.empty();
}
int main()
{
mystack<int> testStack;
testStack.push(1);
testStack.push(5);
testStack.push(3);
testStack.push(2);
testStack.push(8);
cout<<testStack.top()<<endl;
testStack.printOn(std::cout);
}
类的全特化和部分特化
1 全特化
#include<iostream>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
using namespace std;
template <class T>
class mystack
{
public:
void push(T const& elem);
T const& top();
void pop();
bool empty();
void printOn(std::ostream& strm) const
{
for (T const& elem : elementArr)
{
strm << elem <<endl;
}
}
private:
vector<T> elementArr;
};
template<class T>
void mystack<T>::push(T const& elem)
{
elementArr.push_back(elem);
}
template<class T>
T const& mystack<T>::top()
{
assert(!elementArr.empty());
return elementArr.back();
}
template<class T>
void mystack<T>::pop()
{
assert(!elementArr.empty());
elementArr.pop_back();
}
template<class T>
bool mystack<T>::empty()
{
return elementArr.empty();
}
#endif
template<>
class mystack<std::string>
{
public:
void push(std::string const& elem);
std::string const& top();
void pop();
bool empty();
void printOn(std::ostream& strm) const
{
for (std::string const& elem : elementArr)
{
strm << elem <<endl;
}
}
private:
vector<std::string> elementArr;
};
void mystack<std::string>::push(std::string const& elem)
{
elementArr.push_back(elem);
}
std::string const& mystack<std::string>::top()
{
assert(!elementArr.empty());
return elementArr.back();
}
void mystack<std::string>::pop()
{
assert(!elementArr.empty());
elementArr.pop_back();
}
bool mystack<std::string>::empty()
{
return elementArr.empty();
}
int main()
{
mystack<std::string> testStack;
testStack.push("1");
cout<<testStack.top()<<endl;
testStack.printOn(std::cout);
}
上述代码是将mystack全特化为string类型,在实际写代码时,发现如果只有全特化的函数template<>
class mystack<std::string>,没有template <class T>class mystack,会存在编译问题,说明定义全特化的前提是存在泛型的模板函数,并且需要定义在全特化函数之前。
|=== Build: Debug in 3432432423 (compiler: GNU GCC Compiler) ===|
D:\3432432423\main.cpp|56|error: 'mystack' is not a class template|
D:\3432432423\main.cpp|57|error: explicit specialization of non-template 'mystack'|
D:\3432432423\main.cpp|73|error: expected initializer before '<' token|
D:\3432432423\main.cpp|78|error: expected initializer before '<' token|
D:\3432432423\main.cpp|83|error: expected initializer before '<' token|
D:\3432432423\main.cpp|88|error: expected initializer before '<' token|
D:\3432432423\main.cpp||In function 'int main()':|
D:\3432432423\main.cpp|96|error: 'mystack' is not a template|
||=== Build failed: 7 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|
2.部分特化(特化为指针)
#include<iostream>
#include <cstring>
#include <vector>
#include <cassert>
#include <string>
using namespace std;
template<typename T>
class Stack {
private:
std::vector<T> elems; // elements
public:
void push(T elem); // push element
T pop(); // pop element
T top() const; // return top element
bool empty() const
{ // return whether
return elems.empty();
}
};
template<typename T>
void Stack<T>::push (T elem)
{
elems.push_back(elem); // append copy of passed elem
}
template<typename T>
T Stack<T>::pop ()
{
assert(!elems.empty());
T p = elems.back();
elems.pop_back(); // remove last element
return p; // and return it (unlike in the general case)
}
template<typename T>
T Stack<T>::top () const
{
assert(!elems.empty());
return elems.back(); // return copy of last element
}
// partial specialization of class Stack<> for pointers:
template<typename T>
class Stack<T*> {
private:
std::vector<T*> elems; // elements
public:
void push(T* elem); // push element
T* pop(); // pop element
T* top() const; // return top element
bool empty() const
{ // return whether
return elems.empty();
}
};
template<typename T>
void Stack<T*>::push (T* elem)
{
elems.push_back(elem); // append copy of passed elem
}
template<typename T>
T* Stack<T*>::pop ()
{
assert(!elems.empty());
T* p = elems.back();
elems.pop_back(); // remove last element
return p; // and return it (unlike in the general case)
}
template<typename T>
T* Stack<T*>::top () const
{
assert(!elems.empty());
return elems.back(); // return copy of last element
}
int main()
{
Stack<int*> ptrStk;
ptrStk.push(new int(10));
std::cout << *ptrStk.top() << endl;
}
其逻辑与全特化一致,在定义时,不能只定义部分特化的模板,否则会有编译报错。