函数模版与类模版的设计是为了代码重用,它通过参数多态化实现,就是将程序所处理的对象的类型参数化,使得一段程序可以用于处理多种不同类型的对象。
函数模版的一个具体的例子如下:
#includeusing namespace std; template T abs(T x) { return x>0? x:-x; } int main() { int n = 5; double d = -5.5; cout<<"abs(n): "<
需要注意:
1. 函数模版在编译时不会产生目标代码,只有在实例化后才产生目标代码。
2. 被多个源文件引用的函数模版,应当将其函数体一同放入头文件中。
3. 函数指针只能指向函数模版的实例。
类模版:
使用类模版可以使用户为类定义一种模式,使类中的某数据成员、类中成员函数的参数、返回值、局部变量能取任意类型,包括系统类型和自己定义的类型。
类是对事物的抽象,类模版是对不同类公共性质的抽象,是更高层次的抽象。类模版声明的语法如下:
如果需要在类模板以外定义其成员函数,则要采用以下的形式:
使用一个模板类来建立对象时,应按如下形式声明: 9.2 线性群体
线性群体的概念
1. 直接访问(数组类)
2. 顺序访问
3.索引访问
数组类:静态数组在编译时已经确定其大小,后续无法修改,并且静态数组不能避免下标越界。为解决这个问题,我们设计一种动态数组Array,它由任意多个位置连续的、类型相同的元素组成,其元素个数可在程序运行时改变,功能与vector相近。
下面代码我们简单实现vector。
Myvector.hpp:
// // Myvector.hpp // personalaccount // // Created by 刘博文 on 2022/7/18. // #ifndef Myvector_hpp #define Myvector_hpp #include#include #include #include template class MyVector { public: MyVector(int size = 10); ~MyVector(); //访问 T& at(int index) const; T& front() const; T& back() const; T& operator[](int index); //容量 bool empty() const; int size() const; int capacity() const; //修改 void clear(); void insert(int index, const T& d); void remove(int index); void push_back(const T& d); void pop_back(); private: T* data; int length; int current_pos; }; template MyVector ::MyVector(int size) :length(size), current_pos(0) { if (data != nullptr) { delete[] data; data = nullptr; } data = new T[length]; memset(data, 0, length * sizeof(T)); } template MyVector ::~MyVector() { if (data != nullptr) { delete[] data; data = nullptr; } } template T& MyVector ::at(int index) const { assert(index > 0 || index < current_pos); return data[index]; } template T& MyVector ::front() const { assert(current_pos > 0); return data[0]; } template T& MyVector ::back() const { assert(current_pos > 0); return data[current_pos - 1]; } template T& MyVector ::operator[](int index) { assert(index > 0 || index < current_pos); return data[index]; } template bool MyVector ::empty() const { return current_pos == 0 ? true : false; } template int MyVector ::size() const { return current_pos; } template int MyVector ::capacity() const { return length; } template void MyVector ::clear() { current_pos = 0; } template void MyVector ::insert(int index, const T& d) { assert(index > 0 || index < current_pos); if (current_pos == length) { T* temp = new T[length + 10]; memset(temp, 0, (length + 10) * sizeof(T)); memcpy(temp, data, length * sizeof(T)); length += 10; delete[]data; data = nullptr; data = temp; } memcpy(data + index + 1, data + index, (length - index) * sizeof(T)); data[index] = d; // 当前数组指针 +1 current_pos++; } template void MyVector ::remove(int index) { assert(index > 0 || index < current_pos); memcpy(data + index, data + index + 1, (current_pos - index) * sizeof(T)); current_pos--; } template void MyVector ::push_back(const T& d) { // 检查当前数组大小是否可用 if (current_pos == length) { // 扩容,每次扩容 10 个数据大小的空间 T* temp = new T[length + 10]; memset(temp, 0, (length + 10) * sizeof(T)); memcpy(temp, data, length * sizeof(T)); length += 10; delete[] data; data = nullptr; data = temp; } // 插入数据 data[current_pos] = d; // 当前数组指针 +1 current_pos++; } template void MyVector ::pop_back() { assert(current_pos > 0); current_pos--; } #endif
Myvector.cpp
// // Myvector.cpp // personalaccount // // Created by 刘博文 on 2022/7/18. // #include "Myvector.hpp" #includeusing namespace std; int main() { MyVector vec; for (int i = 0; i < vec.capacity(); i++) vec.push_back(i); vec.push_back(10); cout << "capacity: " << vec.capacity() << endl; for (int i = 0; i < vec.size(); i++) cout << vec.at(i) << ", "; cout << endl; vec.insert(0, 5); vec.insert(1, 15); for (int i = 0; i < vec.size(); i++) cout << vec[i] << ", "; cout << endl; vec.remove(1); vec.pop_back(); for (int i = 0; i < vec.size(); i++) cout << vec[i] << ", "; cout << endl; cout << "front: " << vec.front() << ", back: " << vec.back() << endl; return 0; }
上面的代码是之前学习C++时自己的练习,功能为简单实现vector。对比书中的例子,缺少运算符重载、copy构造函数等,一般copy构造函数和运算符重载会同时出现。
链表类:
概念就是数据结构中的链表。存储不连续,需要指针对其数据进行指向。自己定义链表类容易内存泄露导致内存不足程序崩溃,再STL中有定义好的链表类,完全满足我们的需求。
书中有链表类的实现。需要预先定义一个链表结构node,再定义链表数据结构,数据结构的private中需要表头表尾,前驱和当前节点等指针。公有的public包含对链表的操作。
栈和队列:
栈同样是最基础的数据结构,只能从一端访问的线性群体,可访问的为栈顶,另一端为栈底,后进先出。表达式处理方法可用栈数据结构。
栈的基本状态分为:栈空、栈满、一般状态。
栈的基本操作:初始化、入栈、出栈、清空栈、访问栈顶元素、检测栈的状态。
队列只能在一端添加元素,从另一端删除元素。队列状态有:队空、队满、一般状态。
9.3 群体数组组织这节主要介绍了数据的排序方法,这是我们算法和数据结构课的基础内容了,哈哈!主要有插入排序、选择排序、交换排序、顺序查找、折半查找。排序的基础操作就是比较和交换。
9.4 深度探索模版实例化机制
1. 模版与模版实例
2. 隐含实例化
3. 多文件结构中的模版的组织
4. 显示实例化
为模版定义特殊的实现
1. 模版的特化
2. 类模版的偏特化
3. 函数模版的重载



