《C++ Primer Plus》模板类 Template 课本实验,这里是抄写图书上的代码作为备忘测试。
1.模板类
cpp 14.13 模板类,模板类使用关键字 template ,关键字 typename,《C++ Primer Plus》教材上说关键字typename和class是等价的,老的C++98规范使用 class 作为关键字,最新的使用 typename 更贴切。
cpp
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <thread>
#include <mutex>
#include <condition_variable>
// 2025/11/28 learing <<C++ primer plus>> 14.13
// dimon.chen@1181302388@qq.com
template <typename Type>
class Stack
{
private:
enum {MAX = 10}; //const specific to class
Type items[MAX]; // holds stack items
int top; // index of stack item
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type & item); // add item to stack
bool pop(Type &item); // pop top into item
};
template <typename Type>
Stack<Type>::Stack() {
top = 0;
}
template <typename Type>
bool Stack<Type>::isempty() {
return top == 0;
}
template <typename Type>
bool Stack<Type>::isfull()
{
return top == MAX;
}
template <typename Type>
bool Stack<Type>::push(const Type & item) {
if (top < MAX) {
items[top++] = item;
return true;
}
else {
return false;
}
}
template <typename Type>
bool Stack<Type>::pop(Type & item) {
if(top > 0) {
item = items[--top];
return true;
}
else {
return false;
}
}
// declare template Class
//
//
int main(int argc, char *argv[]) {
Stack<std::string> st; // create emptry stack
char ch;
std::string po;
std::cout << "Please enter A to add a purchase order,\n"
<< "P to processs a PO, or O to quit.\n";
while(std::cin >> ch && std::toupper(ch) != 'Q')
{
while (std::cin.get() != '\n')
continue;
if((!std::isalpha(ch))) {
std::cout << '\a';
continue;
}
switch(ch) {
case 'A':
case 'a':
std::cout << "Enter a PO number to add:" ;
std::cin >> po;
if(st.isfull())
std::cout << "Stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p':
if(st.isempty())
std::cout << "stack already emptry\n";
else
{
st.pop(po);
std::cout << "Po #" << po << " poped\n";
break;
}
}
std::cout << "Please enter A to add a purchase order,\n"
<< "P to processs a PO, or O to quit.\n";
}
std::cout << "Bye\n";
return 0;
}
2.模板类具体化
《C++ Primer Plus》 cpp 14.15 实验,正确的使用 'const char *' 作为类型参数来实例化模板类。
cpp
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <thread>
#include <vector>
#include <cstdlib>
// 2025/11/28 learing <<C++ primer plus>> 14.15
// dimon.chen@1181302388@qq.com
template <typename Type>
class Stack {
private:
enum {SIZE = 10}; // default size
int stacksize;
Type *items; // hold stack items
int top;
public:
explicit Stack(int ss = SIZE); // explicit one parameter constructor
Stack(const Stack & st); // copy constructor
~Stack() {delete [] items;}; // deconstructor
bool isemptry() { return top == 0;}
bool isfull() {return top > stacksize;}
bool push(const Type &item); // add item to stack
bool pop(Type &item); // pop top of stack to item
Stack & operator = (const Stack & st);
};
template <typename Type>
Stack<Type>::Stack(int ss) : stacksize(ss), top(0)
{
items = new Type [stacksize];
}
template <typename Type>
Stack<Type>::Stack(const Stack &st) {
stacksize = st.stacksize;
top = st.top;
items = new Type [stacksize];
// deep copy
for(int i=0; i<top; i++)
items[i] = st.items[i];
}
template <typename Type>
bool Stack<Type>::push(const Type &item) {
if(top < stacksize) {
items[top++] = item;
return true;
}
else
return false;
}
template <class Type>
bool Stack<Type>::pop(Type &item) {
if(top > 0) {
item = items[--top];
return true;
}
else
return false;
}
// must judge self operatior = assigned
// because if you free , and then the data is lost
//
template <typename Type>
Stack<Type> & Stack<Type>::operator=(const Stack<Type> &st) {
if(this == &st) // check self operator =
return *this;
delete [] items;
stacksize = st.stacksize;
top = st.top;
items = new Type [stacksize];
// deep copy
for(int i=0; i<stacksize; i++)
items[i] = st.items[i];
return *this;
}
const int num = 10;
int main(int argc, char *argvp[])
{
std::srand(std::time(0));
std::cout << "Please enter stack size:";
int stacksize;
std::cin >> stacksize;
// create empty stack with stacksize slots
Stack<const char *> st(stacksize); // type parameter
// in bascket
const char * in[num] = {
"1: HandK Gilgames",
"2: Kiki Ishat",
"3: Betty, Rocket",
"4: Ian Flagranti",
"5: Woflgang Kibble",
"6: Portis Koop",
"7: Joy Almodo",
"8: Xaveris Papriks",
"9: Juan Moore",
"10: Misha Mache"
};
// out backet
const char *out[num];
int processed = 0;
int nextin = 0;
while(processed < num) {
if (st.isemptry()) {
st.push(in[nextin++]);
}
else if(st.isfull()) {
st.pop(out[processed]);
}
else if(std::rand()%2 && nextin < num) {
st.push(in[nextin++]);
}
else {
st.pop(out[processed++]);
}
}
for(int i=0; i<num; i++)
{
std::cout << out[i] << std::endl;
}
return 0;
}
3.非类型参数模板
4.模板的迭代
这两个实验何在了一起,使用了类模板的非类型参数(表达式参数),并且使用递归模板定义了 ArrayTP<ArrayTP<int, 5>, 10> twodee,基于模板的迭代,twodee 是一个报了10个元素的数组,每个元素都是一个包含了5个int元素的数组。
cpp
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <mutex>
#include <condition_variable>
#include <thread>
template <typename T, int n>
class ArrayTp
{
private:
T ar[n];
public:
ArrayTp() {} //default constructor function
explicit ArrayTp(const T & v); // explicat one parameter constructior
virtual T & operator[](const int i);
virtual T operator[](const int i) const;
};
template <typename T, int n>
ArrayTp<T,n>::ArrayTp(const T & v) {
for(int i=0; i<n; i++)
ar[i] = v;
}
template <typename T, int n>
T & ArrayTp<T,n>::operator[](const int i)
{
if(i < 0 || i > n) {
std::cerr << "Error in array limists: " << i << " is out of ragnge\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
template <typename T, int n>
T ArrayTp<T,n>::operator[](const int i) const
{
if(i<0 || i>n)
{
std::cerr << "Error in array limists: " << i << " is out range\n";
std::exit(EXIT_FAILURE);
}
return ar[i];
}
// no-type parameter , or expression paramter
// const expression
//
int main(int argc, char *argv[])
{
ArrayTp<int, 10> sums;
ArrayTp<double , 10> aver;
ArrayTp< ArrayTp<int, 5>, 10> twodee;
int i, j;
for(int i=0; i<10; i++) {
sums[i] = 0;
for(j=0; j< 5; j++) {
twodee[i][j] = (i+1) *(j+1);
sums[i] += twodee[i][j];
}
aver[i] = sums[i] / 10;
}
for(i=0; i<10; i++) {
for(j=0; j<5; j++) {
std::cout.width(2);
std::cout << twodee[i][j] << ' ';
}
std::cout << ": sum = ";
std::cout.width(3);
std::cout << sums[i] << ", average = " << aver[i] << std::endl;
// std::cout << std::endl;
}
return 0;
}
- 《C++ Primer Plus》14.19 实验带有多个类型参数的类模板
cpp
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <vector>
#include <queue>
#include <unordered_map>
#include <mutex>
#include <condition_variable>
#include <chrono>
#include <thread>
// 2025/11/28 learing <<C++ primer plus>> 14.15
// dimon.chen@1181302388@qq.com
template <typename T1, class T2> // 'typename' and 'class' is both support
class Pair {
private:
T1 a;
T2 b;
public:
T1 & first();
T2 & second();
T1 first() const {return a;}
T2 second() const {return b;}
Pair(const T1 &aval, const T2 &bval) : a(aval), b(bval) {}
Pair() {}
};
template <typename T1, typename T2>
T1 & Pair<T1, T2>::first() {
return a;
}
template <typename T1, typename T2>
T2 & Pair<T1, T2>::second()
{
return b;
}
int main(int argc, char *argv[])
{
Pair<std::string, int> ratings[4] = {
Pair<std::string, int> ("The Purpled Duck", 5),
Pair<std::string, int> ("Jaquie's Friscon AI Frecso", 4),
Pair<std::string, int> ("Cafe Souffles",5),
Pair<std::string, int> ("Berfite's Eats", 3)
};
int joints = sizeof(ratings) / sizeof(Pair<std::string, int>);
std::cout << "Ratting: \t Eattery\n";
for(int i=0; i<joints; i++) {
std::cout << ratings[i].second() << ":\t"
<< ratings[i].first() << std::endl;
}
std::cout << "opps! Received ratting:\n";
ratings[3].first() = "Berties' Fab Eats"; // return value is &
ratings[3].second() = 6;
std::cout << ratings[3].second() << ":\t"
<< ratings[3].first() << std::endl;
return 0;
}
- 《C++ Primter Plus》14.20 模板类成员函数是一个模板函数
cpp
template <typename T>
class beta
{
private:
template <typename V>
class hold
{
private:
V val;
public:
hold(V v = 0) : val(v) {}
void show() const { std::cout << val << std::endl;}
V value() const {return val;}
};
hold<T> q; // template object
hold<int> n; // template object
public:
beta(T t, int i) : q(t), n(i) {}
template <typename U> // template function
U blab(U u, T t)
{
return (n.value() + q.value()) * u /t;
}
void show() const { q.show(); n.show();}
};
int main(int argc, char *argv[]) {
beta<double> guy(3.5, 3);
std::cout << "T was set to double\n";
guy.show();
std::cout << "V wase set to T, which is double, then V was set to int\n";
std::cout << guy.blab(10, 2.3) << std::endl;
std::cout << "U wase set to int\n";
std::cout << guy.blab(10.0, 2.3) << std::endl;
std::cout << "U was set to double\n";
std::cout << "Done";
return 0;
}