9.11学习记录

一.类模板特化

1.为什么需要这个?

类模板特化是一种在C++中提供泛型编程的手段。泛型编程是一种编程范式,让程序员在强类型语言(如C++)环境中编写高度可复用的代码。

让我们首先理解什么是类模板。类模板是一种创建泛型类的工具,它允许程序员创建适应多种数据类型的类,而不需要为每一种数据类型编写一个单独的类。例如,你可以创建一个名为 MyType 的模板类,然后使用 MyType<int>MyType<double>MyType<std::string> 等来实例化不同类型的对象。

然而,有时候你可能需要对特定类型的模板进行一些特殊的处理。例如,你可能有一个模板类,它在处理整数时需要一个特殊的算法,而在处理其他类型时需要另一个算法。在这种情况下,你可以使用类模板特化。

类模板特化是一种声明一个模板的特殊行为的方式,当模板被特定类型的参数实例化时,这个特殊行为就会发生。例如,你可以特化 MyType<int>,使其行为与其他类型的 MyType 不同。

总的来说,类模板特化提供了一种在保持代码复用的同时,能够对特定类型进行特殊处理的方法,这是泛型编程中的一个强大工具。

/* 类模板特化.cpp */
//设计一通用数组类,它能够直接存取数组元素,并能够对数组进行从大到小的排序。

#include <cstring>
#include <iostream>
using namespace std;
const int Size = 5;
template <class T> class Array {
private:
  T a[Size];

public:
  Array() {
    for (int i = 0; i < Size; i++) {
      a[i] = 0;
    }
  }
  T &operator[](int i);
  void Sort();
};

template <class T> T &Array<T>::operator[](int i) {
  if (i < 0 || i > Size - 1) {
    cout << "\n数组下标越界!" << endl;
    exit(1);
  }
  return a[i];
}

template <class T> void Array<T>::Sort() {
  int p;
  for (int i = 0; i < Size - 1; i++) {
    p = i;
    for (int j = i; j < Size; j++) {
      if (a[p] < a[j])
        p = j;
    }
    T t = a[p];
    a[p] = a[i];
    a[i] = t;
  }
}
// template <> 返回类型 类模板名<特化的数据类型>::特化成员函数名(参数表){}
template <> 
void Array<char *>::Sort() {
  int p;
  for (int i = 0; i < Size - 1; i++) {
    p = i;
    for (int j = i + 1; j < Size; j++)
      if (strcmp(a[p], a[j]) < 0)
        p = j;
    char *t = a[p];
    a[p] = a[i];
    a[i] = t;
  }
}

int main() {
  Array<int> a1;
  Array<char *> b1;
  a1[0] = 1;
  a1[1] = 23;
  a1[2] = 6;
  a1[3] = 3;
  a1[4] = 9;
  a1.Sort();
  for (int i = 0; i < 5; i++)
    cout << a1[i] << "\t";
  cout << endl;
  b1[0] = "x1";
  b1[1] = "ya";
  b1[2] = "ad";
  b1[3] = "be";
  b1[4] = "bc";
  b1.Sort();
  for (int i = 0; i < 5; i++)
    cout << b1[i] << "\t";
  cout << endl;
  
}

还可以进行参数的强制转换

/* 求最大值.cpp */
// Eg9-2.cpp
#include <iostream>
using namespace std;
template <class T> T Max(T a, T b) { return (a > b) ? a : b; }
/*
C++在实例化函数模板的过程中,只是简单地将模板参数替换成调用实参的类型,并以此生成模板函数,不会进行参数类型的任何转换。
*/
int main() {
	double a = 2, b = 3.4;
	float c = 5.1, d = 3.2;
	//在模板调用时进行参数类型的强制转换
	cout << "2, 3.2    的最大值是:" << Max(double(2), 3.2) << endl;
	cout << "a, c    的最大值是:" << Max(float(a), c) << endl;
	//显示指定函数模板实例化的参数类型
	cout << "'a', 3    的最大值是:" << Max<int>('a', 3) << endl;

}

函数模板参数可以是类属参数,也可以包括普通类型的参数

/* 例1.cpp */
//函数模板参数可以是类属参数,也可以包括普通类型的参数
#include <iostream>
using namespace std;

template <class T>
//实现降序
void sort(T *a, int n) {
  for (int i = 0; i < n; i++) {
    int p = i;
    for (int j = i; j < n; j++)
      if (a[p] < a[j])
        p = j;
    T t = a[i];
    a[i] = a[p];
    a[p] = t;
  }
}
template <class T> void display(T &a, int n) {
  for (int i = 0; i < n; i++)
    cout << a[i] << "\t" << endl;
}

int main(int argc, char const *argv[]) {
  int a[] = {1, 41, 2, 5, 8, 21, 23};
  char b[] = {'a', 'x', 'y', 'e', 'q', 'g', 'o', 'u'};
  sort(a, 7);
  sort(b, 8);
  display(a, 7);
  display(b, 8);
  
  return 0;
}

二.模拟栈

栈是一种线性数据结构,其操作遵循后进先出(LIFO)的原则。这意味着最后一个被添加到栈中的元素将是第一个被移除的元素。

栈具有以下基本操作:

  1. push(x):将元素x添加到栈的顶部。
  2. pop:删除栈顶的元素并返回该元素。
  3. top(x):返回栈顶的元素但不删除。
  4. empty:检查栈是否为空,返回True或False。

栈在许多算法和程序设计中都有应用,例如在计算机科学中的深度优先搜索,括号匹配,后缀/中缀/前缀表达式的求值,函数调用和递归等场景中。

在日常生活中,我们可以将栈理解为一种累积或者堆积的方式,比如叠盘子,最后放上去的盘子将是第一个被取走的。

/* 模拟栈.cpp */
/*
设计一个堆栈的类模板Stack,在模板中用类型参数T表示栈中存放的数据,用非类型参数MAXSIZE代表栈的大小。
*/
#include <iostream>
using namespace std;

template <class T, int MAXSIZE> class Stack {
private:
    T elem[MAXSIZE];
    int top;

public:
    Stack() { top = 0; };
    void push(T e);
    T pop();
    bool empty() {
        if (top <= -1)
            return 1;
        else
            return 0;
    }
    void setEmpty() { top = -1; }
    bool full() {
        if (top >= MAXSIZE - 1) {
            return 1;
        }
        else
            return 0;
    }
};
/*
原型:
template <模板参数列表>
返回值类型 类模板名<模板参数名表>::成员函数名 (参数列表){};
*/
template <class T, int MAXSIZE> void Stack<T, MAXSIZE>::push(T e) {
    if (full()) {
        cout << "栈已满,不能再添加元素了!";
        return;
    }
    elem[++top] = e;
}

template <class T, int MAXSIZE> T Stack<T, MAXSIZE>::pop() {
    if (empty()) {
        cout << "栈已空,不能再弹出元素了!" << endl;
        return 0;
    }
    return elem[top--];
}

int main(int argc, char const* argv[]) {
    //类模板实例化
    Stack<int, 10> iStack;
    Stack<char, 10> cStack;
    iStack.setEmpty();
    cStack.setEmpty();
    cout << "-------intStack----\n";
    int i;
    for (i = 1; i < 11; i++)
        iStack.push(i);
    for (i = 1; i < 11; i++)
        cout << iStack.pop() << "\t";
    cout << "\n\n-------charStack----\n";
    cStack.push('A');
    cStack.push('B');
    cStack.push('C');
    cStack.push('D');
    cStack.push('E');
    for (i = 1; i < 6; i++)
        cout << cStack.pop() << "\t";
    cout << endl;

    return 0;
}

三.模板特化

/* 模板特化.cpp */
// Eg9-6.cpp
#include <cstring>
#include <iostream>
using namespace std;
template <class T> T Max(T a, T b) { return (a > b) ? a : b; }
//特化
// template <> 返回类型 函数名<特化的数据类型>(参数表) {}
template <> const char *Max<const char *>(const char *a, const char *b) {
  return (strcmp(a, b) >= 0) ? a : b;
}
template <> char *Max<char *>(char *a, char *b) {
  return (strcmp(a, b) >= 0) ? a : b;
}
int main() {
  float c = 5.1, d = 3.2;
  char s1[] = "xyce", s2[] = "xbv";
  cout << "2,3的最大值是:" << Max(3, 2) << endl;
  cout << "c,d的最大值是:" << Max(c, d) << endl;
  cout << Max("xbv", "xyce") << endl;
  cout << Max(s1, s2) << endl;
  
}
/*
① 当程序中同时存在模板和它的特化时,特化将被优先调用;
②
在同一个程序中,除了函数模板和它的特化外,还可以有同名的普通函数。其区别在于C++会对普通函数的调用实参进行隐式的类型转换,
但不会对模板函数及特化函数的参数进行任何形式的类型转换。

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值