《C++ Primer Plus》模板类 Template 课本实验

《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;
}
  1. 《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;
}
  1. 《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;
}
相关推荐
码力码力我爱你3 小时前
Harmony OS C++实战
开发语言·c++
Vect__3 小时前
别再只懂 C++98!C++11 这7个核心特性,直接拉开你与普通开发者的差距
c++
想唱rap3 小时前
C++ map和set
linux·运维·服务器·开发语言·c++·算法
小欣加油5 小时前
leetcode 1018 可被5整除的二进制前缀
数据结构·c++·算法·leetcode·职场和发展
玖剹6 小时前
递归练习题(四)
c语言·数据结构·c++·算法·leetcode·深度优先·深度优先遍历
西部秋虫6 小时前
YOLO 训练车牌定位模型 + OpenCV C++ 部署完整步骤
c++·python·yolo·车牌识别
雾岛听蓝8 小时前
C++ 类和对象(一):从概念到实践,吃透类的核心基础
开发语言·c++·经验分享·笔记
Dream it possible!9 小时前
LeetCode 面试经典 150_图_克隆图(90_133_C++_中等)(深度优先:DFS)
c++·leetcode·面试·
鸭子程序员9 小时前
c++ 算法
开发语言·c++·算法