目录
1. 函数模板
2. 类模板
3. 典型范例——链栈类模板的设计和实现
4. 内嵌容器的栈类模板的设计和实现
1. 函数模板
- 对处理逻辑相同、只是处理数据类型不同的函数,将其中的类型参数化,抽象成函数模板,再有编译器通过函数模板产生模板函数。
函数模板声明的一般格式:
template返回值类型 函数模板名(形参表);
函数模板定义的一般格式:
template返回值类型 函数模板名(形参表) { ... }
- 上述函数模板声明或定义中,template后尖括号内的类型参数名可以有一个或多个,每个类型参数名前必须有关键字typename,代表一个类名,这个关键字可以用class代替
//两个T类对象间求较大的对象Max函数模板声明如下 //声明 templateconst T& Max(const T& A, const T& b); //定义 template const T& Max(const T& A, const T& b) { if (a > b) return a; else return b; }
函数模板重载
templateconst T& Max(const T& a, const T& b); //两个中找出较大者 template const T& Max(const T& a, const T& b, const T& c); //三个中找出较大值 template const T& Max(const T A[], int iCount); //iCount个元素数组中找出最大者 template const T& Max(const T& a, const T& b) { if (a > b) return a; else return b; } template const T& Max(const T& a, const T& b, const T& c) { if (a > b) { if (a > c) return a; else return c; } else { if (b > c) return b; else return c; } } template const T& Max(const T A[], int iCount) { int m = 0; for (int i = 1; i < iCount; i++) { if (A[i] > A[m]) { m = i; } return A[m]; } }
函数模板和函数
- C++容许定义同名的函数模板和函数,重载函数模板和函数后,编译器首先匹配类型完全相同的函数,如果匹配失败,再寻求函数模板进行匹配
const char* Max(const char* a, const char* b)
{
if (strcmp(a, b) >= 0)
{
return a;
}
else
{
return b;
}
}
template
const T& Max(const T& a, const T& b)
{
if (a > b)
return a;
else
return b;
}
2. 类模板
类模板定义和成员函数定义
templateclass 类模板名 { ... }
templateclass 类模板名<类型参数名>::成员函数名(形参表) { ... }
实现了动态数组功能的Array类模板的简单样例:
#include#include using namespace std; template class Array { private: T* elem; int size; public: Array(int sz) :size(sz) { elem = new T[size]; } ~Array() { delete[] elem; } T& operator[](int i); }; template T& Array ::operator[](int i) //元素引用,可作为左值或右值 { if (i < 0 || i >= size) { throw "Invalid Index"; } return elem[i]; } int main() { int a[] = { 1, 9, 7, 5, 6, 3 }; int n = 6; Array obj(n); int i; for (i = 0; i < n; i++) { obj[i] = a[i]; } for (i = 0; i < n; i++) { cout << obj[i] << " "; } cout << endl; Array strObj(n); strObj[0] = "Test"; strObj[1] = "String"; strObj[2] = "again"; for (i = 0; i < n; i++) { cout << strObj[i] << " "; } cout << endl; }
内联函数成员、非类型参数、函数调用运算符重载
#include#include using namespace std; template class Array { private: T elem[MaxSIZE]; public: inline T& operator[](int i); }; template T& Array ::operator[](int i) //元素引用,可作为左值或右值 { if (i < 0 || i >= MaxSIZE) { throw "Invalid Index"; } return elem[i]; } int main() { int a[] = { 1, 9, 7, 5, 6, 3 }; const int n = 6; Array obj; int i; for (i = 0; i < n; i++) { obj[i] = a[i]; } for (i = 0; i < n; i++) { cout << obj[i] << " "; } cout << endl; Array strObj; strObj[0] = "Test"; strObj[1] = "String"; strObj[2] = "again"; for (i = 0; i < n; i++) { cout << strObj[i] << " "; } cout << endl; }
3. 典型范例——链栈类模板的设计和实现
#include
#include
using namespace std;
template
class CStack;
template
void Dump(ostream& os, CStack& rhs);
template
class CStack
{
struct Node
{
T data;
Node* next;
};
private:
Node* m_sp;
public:
CStack() :m_sp(nullptr) {}
CStack(const CStack& rhs);
CStack(CStack&& rhs);
CStack& operator=(const CStack& rhs);
CStack& operator=(CStack&& rhs);
~CStack();
inline void push(const T& x);
inline bool empty()const;
inline const T& top()const;
inline void pop();
friend void Dump(ostream& os, CStack& rhs);
};
template
CStack::CStack(const CStack& rhs) //copy construction
{
m_sp = nullptr;
if (rhs.empty())
return;
//Copy the first node of the linked list
m_sp = new Node;
Node* q = rhs.m_sp;
m_sp->data = q->data;
//Copy the other nodes of the linked list
Node* last = m_sp;
q = q->next;
while (q != nullptr)
{
Node* p = new Node;
p->data = q->data;
last->next = p;
last = p;
q = q->next;
}
last->next = nullptr;
}
template
CStack::CStack(CStack&& rhs)
{
m_sp = nullptr;
swap(m_sp, rhs.m_sp);
}
template
CStack& CStack::operator=(const CStack& rhs) //Assignment operator overload
{
if (this == &rhs)
return *this;
CStack tmp(rhs);
swap(tmp.m_sp, this->m_sp);
return *this;
}
template
CStack& CStack::operator=(CStack&& rhs)
{
if (this == &rhs)
return *this;
swap(rhs.m_sp, this->m_sp);
return *this;
}
template
CStack::~CStack()
{
while (m_sp != nullptr)
{
Node* p = m_sp;
m_sp = m_sp->next;
delete p;
}
}
template
void CStack::push(const T& x)
{
Node* p = new Node;
p->data = x;
p->next = m_sp;
m_sp = p;
}
template
bool CStack::empty()const
{
return (m_sp == nullptr);
}
template
const T& CStack::top()const
{
return m_sp->data;
}
template
void CStack::pop()
{
Node* p = m_sp;
m_sp = p->next;
delete p;
}
//倒出显示栈内容函数模板定义
template
void Dump(ostream& os, CStack& S)
{
while (S.m_sp != nullptr)
{
os << S.top() << " ";
S.pop();
}
os << endl;
}
//分析执行指令函数模板
template
void Parse()
{
int n;
cin >> n;
CStackS1, S2;
int v, i;
T x;
for (i = 0; i < n; i++)
{
cin >> v >> x;
if (v == 1)
S1.push(x);
else
S2.push(x);
}
CStack S3(S1), S4;
S4 = S2;
CStack S5(std::move(S3)), S6;
S6 = std::move(S4);
Dump(cout, S1);
Dump(cout, S2);
Dump(cout, S5);
Dump(cout, S6);
}
int main()
{
string strType;
while (cin >> strType)
{
if (strType == "int")
Parse();
else if (strType == "string")
Parse();
}
return 0;
}
4. 内嵌容器的栈类模板的设计和实现
#include
#include
#include
#include
#include
using namespace std;
template
class CStack;
template
void Dump(ostream& os, CStack& rhs);
template >
class CStack
{
private:
ContT m_cont;
public:
typedef T valueType;
inline void push(const T& x);
inline bool empty()const;
inline const T& top()const;
inline void pop();
friend void Dump(ostream& os, CStack& rhs);
};
template
void CStack::push(const T& x)
{
m_cont.push_back(x);
}
template
bool CStack::empty()const
{
return (m_cont.empty());
}
template
const T& CStack::top()const
{
return m_cont.back();
}
template
void CStack::pop()
{
m_cont.pop_back();
}
template
void Dump(ostream& os, CStack& S)
{
while (!S.m_cont.empty())
{
os << S.top() << " ";
S.pop();
}
cout << endl;
}
template>
void Parse()
{
int n;
cin >> n;
CStack S1, S2;
int v, i;
T x;
for (i = 0; i < n; i++)
{
cin >> v >> x;
if (v == 1)
S1.push(x);
else
S2.push(x);
}
CStack S3(S1), S4;
S4 = S2;
CStack S5(std::move(S3)), S6;
S6 = std::move(S4);
Dump(cout, S1);
Dump(cout, S2);
Dump(cout, S5);
Dump(cout, S6);
}
int main()
{
string strType;
while (cin >> strType)
{
if (strType == "int")
Parse();
else if (strType == "string")
Parse>();
}
return 0;
}
#include#include #include #include
#include using namespace std; template class CStack; template void Dump(ostream& os, CStack & rhs); template > class CStack { private: ContT m_cont; public: typedef T valueType; inline void push(const T& x); inline bool empty()const; inline const T& top()const; inline void pop(); friend void Dump (ostream& os, CStack& rhs); }; template void CStack ::push(const T& x) { m_cont.push_back(x); } template bool CStack ::empty()const { return (m_cont.empty()); } template const T& CStack ::top()const { return m_cont.back(); } template void CStack ::pop() { m_cont.pop_back(); } template void Dump(ostream& os, CStack & S) { while (!S.m_cont.empty()) { os << S.top() << " "; S.pop(); } cout << endl; } template > void Parse() { int n; cin >> n; CStack S1, S2; int v, i; T x; for (i = 0; i < n; i++) { cin >> v >> x; if (v == 1) S1.push(x); else S2.push(x); } CStack S3(S1), S4; S4 = S2; CStack S5(std::move(S3)), S6; S6 = std::move(S4); Dump(cout, S1); Dump(cout, S2); Dump(cout, S5); Dump(cout, S6); } int main() { string strType; while (cin >> strType) { if (strType == "int") Parse (); else if (strType == "string") Parse >(); } return 0; }



