C++类模板与函数模板基础详细讲解
函数模板
当我们想要定义一个可以支持泛型的函数时,就要采用函数模板的方式了。所谓泛型就是可以支持多种类型的操作,比如我们定义一个compare操作,他可以根据传递给他的参数类型动态调用对应的函数版本,实现多种类型的比较。
template <typename T> int compare(const T &v1, const T &v2) { if (v1 < v2) return -1; if (v2 < v1) return 1; return 0; }
比较函数是一个模板函数,它支持T类型的对象比较,模板函数定义的规则是用template 声明模板的类型为T,然后用T做参数即可。
调用的规则传递实参就可以了,前提是实参的类型要支持比较大小,如果是类的类型我们可以重载比较运算符。
int res = compare(3, 4); cout << "compare(3,4) res is " << res << endl; vector<int> v1 = {1, 3, 5}; vector<int> v2 = {2, 4}; res = compare(v1, v2); cout << "compare(v1, v2) res is " << res << endl;
我们分别传递了int类型和vector类型的参数作为compare比较的参数。模板函数也支持多个类型,我们可以再定义一个支持多个参数类型的模板函数
template <typename T, typename U> int printData(const T &t, const U &u) { cout << "t is " << t << endl; cout << "u is " << u << endl; }
调用规则和上边类似,传递两个不同类型即可
printData(3.4, "hello world");
模板函数也支持非参数类型,用已知类型定义变量
template <unsigned N, unsigned M> int compareArray(const char (&p1)[N], const char (&p2)[M]) { return strcmp(p1, p2); }
compareArray的模板里用了已知类型unsigned定义了两个变量N和M。
调用的时候N和M会自动根据实参获取值
res = compareArray("hello zack", "nice to meet u"); cout << "compareArray(" << "hello zack " << ", nice to meet u" << ") res is " << res << endl;
M和N就是传递的两个数组的长度。
类模板
我们实现一个模板类,使其支持类似vector的操作,包括push_back, empty, back, 以及pop_back,取索引[]操作等。
//定义模板类型的blob template <typename T> class Blob { public: typedef T value_type; typedef typename std::vector<T>::size_type size_type; //构造函数 Blob() { data = make_shared<std::vector<T>>(); } Blob(std::initializer_list<T> il) { data = make_shared<std::vector<T>>(il); // for (const T &m : il) // { // data->push_back(m); // } } // Blob 中元素数目 size_type size() const { return data->size(); } bool empty() const { return data->empty(); } //添加和删除元素 void push_back(const T &t) { data->push_back(t); } //移动版本的push_back void push_back(const T &&t) { data->push_back(std::move(t)); } //删除元素 void pop_back(); //元素访问 T &back(); T &operator[](size_type i); private: std::shared_ptr<std::vector<T>> data; //校验数据是否有效 void check(size_type i, const std::string &msg) const; };
我们在类外实现check, pop_back, back, 以及[]操作。
template <typename T> void Blob<T>::check(size_type i, const std::string &msg) const { if (i >= data->size()) throw std::out_of_range(msg); } template <typename T> void Blob<T>::pop_back() { if (data->empty()) { return; } data->pop_back(); } template <typename T> T &Blob<T>::back() { return data->back(); } template <typename T> T &Blob<T>::operator[](size_type i) { check(i, "index out of range"); return (*data)[i]; }
每一个类的成员函数在类外实现时都要声明template。
类模板的使用如下
void use_classtemp() { Blob<int> ia; Blob<int> ia2 = {0, 1, 2, 3, 5}; Blob<string> ia3 = {"hello ", "zack", "nice"}; for (size_t i = 0; i < ia2.size(); i++) { ia2[i] = i * i; } for (size_t i = 0; i < ia2.size(); i++) { cout << ia2[i] << endl; } for (size_t i = 0; i < ia3.size(); i++) { string_upper(ia3[i]); } for (size_t i = 0; i < ia3.size(); i++) { cout << ia3[i] << endl; } const auto &data = ia3.back(); cout << data << endl; ia3.pop_back(); const auto &data2 = ia3.back(); cout << data2 << endl; }
总结
到此这篇关于C++类模板与函数模板基础详细讲解的文章就介绍到这了,更多相关C++类模板与函数模板内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
Clion-MinGW编译后的exe文件添加ico图标的操作方法
这篇文章主要介绍了Clion-MinGW编译后的exe文件添加ico图标的操作方法,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2022-07-07
最新评论