3. STL编程三
1. 算法容器的使用:
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm> //算法,共包含108个算法
#include <numeric> //整数 using namespace std;
using namespace std::placeholders; //用于bind()函数的"_1"参数 struct MyStruct
{
int operator()(int data) //对()进行重载-->伪函数
{
return data % == ;
}
}; int get(int data)
{
return data % == ;
} struct my
{
int get(int data)
{
return data % == ;
}
}; int main()
{
vector<int> myint{ ,,,,,,,,, }; //创建容器
//法一:lambda表达式
int num1 = count_if(myint.begin(), myint.end(), [](int data)->bool {return data % == ; }); //偶数个数
//法二:伪函数(匿名对象)
int num2 = count_if(myint.begin(), myint.end(), MyStruct()); //MyStruct()匿名对象
//法三:有名对象
MyStruct my1;
int num3 = count_if(myint.begin(), myint.end(), my1);
//法四:函数
int num4 = count_if(myint.begin(), myint.end(), get);
//法五:成员函数(函数绑定器)
my my2;
auto fun = bind(&my::get, &my2, _1);
int num5 = count_if(myint.begin(), myint.end(), fun); cout << num1 << endl; //
cout << num2 << endl; //
cout << num3 << endl; //
cout << num4 << endl; //
cout << num5 << endl; // system("pause");
return ;
}
1.1 加入函数模板如下:
#include <iostream>
#include <functional>
#include <vector>
#include <algorithm> //算法,共包含108个算法
#include <numeric> //整数 using namespace std;
using namespace std::placeholders; //用于bind()函数的"_1"参数 template<class T>
bool getT(T data)
{
return data % == ;
} int main()
{
vector<int> myint{ ,,,,,,,,, }; //创建容器 int num6 = count_if(myint.begin(), myint.end(), getT<int>);
cout << num6 << endl; // system("pause");
return ;
}
2. 模板的展开 ==> 属于模板元的范畴
#include <iostream>
#include <cstdarg>
using namespace std; template<class T>
void show(T t)
{
cout << t << " ";
} template<class...Args>
void all(Args...args)
{
int arr[] = { (show(args),)... }; //使用数组进行展开
} template<class...Args>
void allIt(Args...args)
{
int arr[] = { (show(args),)... }; //int arr[],用来约束展开多少层,保存在数组里面,[]不能省
} int main()
{
all(, , , , );
cout << endl;
all(, , , , , , , );
cout << endl;
allIt(, 'A', "", 7.89);
cout << endl; system("pause");
return ;
}
3. 函数模板推理机制:
#include <iostream>
using namespace std; template<typename T>
void go(T t) //将类型泛型
{
cout << typeid(T).name() << endl;
//cout << t << endl;
cout << "T:" << endl;
} template<int i> //模板之间也可以重载
void go() //数据可以为任意数据(相当于数字模板)
{
cout << i << endl;
} template<typename T>
void go(T *t) //将类型泛型
{
cout << typeid(T).name() << endl;
cout << "T *:" << t << endl;
} int main()
{
/*
go(31 - 2); //调用泛型函数模板 go<31 - 2>(); //调用数字模板 go<decltype(10 + 2)>(1234); //调用泛型函数模板,可以用decltype获取数据类型
*/ go(nullptr); //nullptr不是指针类型,是一种自定义的数据类型表示空指针而已,调用go(T t) int *p = nullptr; //调用go(T *t)
go(p); system("pause");
return ;
}
4. 函数指针与函数模板:
4.1 函数模板赋值给函数指针:
#include <iostream>
using namespace std; template<class T>
void show(T t)
{
cout << t << endl;
} struct MyStruct
{
template<class T>
void show(T t)
{
cout << t << endl;
} void go()
{
show();
}
}; //函数模板赋值给函数指针
int main()
{
//void(*p)() = show<int>; //无法从“void (__cdecl *)(T)”转换为“void (__cdecl *)(void)”
void(*p1)(int i) = show<int>;
void(*p2)(double db) = show<double>; system("pause");
return ;
}
4.2 如何调用结构体中的函数模板?
//如何调用结构体中的函数模板?
int main()
{
MyStruct my1;
my1.go(); //结构体内部调用结构体中的函数模板 my1.show(12.3); //外部直接调用结构体中的函数模板
my1.show('A');
my1.show<int>('A'); system("pause");
return ;
}
4.3 如何绑定结构体内部的函数模板?
#include <iostream>
#include <functional> using namespace std;
using namespace std::placeholders; template<class T>
void show(T t)
{
cout << t << endl;
} struct MyStruct
{
template<class T>
void show(T t)
{
cout << t << endl;
} template<class T>
void showit(T t1, T t2)
{
cout << t1 << " " << t2 << endl;
} void go()
{
show();
}
}; //如何绑定结构体内部的函数模板?
int main()
{
MyStruct my1;
auto fun = bind(&MyStruct::showit<int>, &my1, , );
fun(); system("pause");
return ;
}
5. 函数模板、模板函数与类模板:
5.1 什么是函数模板?什么是模板函数?
函数模板就是上面所讲的函数模板,而模板函数则是实例化的函数模板。
#include <iostream>
using namespace std; /*函数模板,不调用不编译*/
template<class T>
T add(T a, T b)
{
return a + b;
} int main()
{
add(, ); /*模板函数,也就是实例化的函数模板,自动根据参数推理*/
add<double>(, 1.2); /*模板函数*/ system("pause");
return ;
}
5.2 类成员函数模板:
#include <iostream>
using namespace std; class myclass
{
public:
template<class T> //类成员函数模板
T add(T a, T b)
{
return a + b;
} template<class T> //静态函数模板
static T sub(T a, T b)
{
return a - b;
}
}; int main()
{
myclass *p = nullptr;
int num1 = p->add<int>(, ); //强行指定的模板函数,当做类成员函数调用
int num2 = p->add(, ); //自动推理的模板函数
cout << num1 << endl;
cout << num2 << endl; int num3 = myclass::sub( , );
cout << num3 << endl; system("pause");
return ;
}
6. 模板在类中的应用:
#include <iostream>
#include <cstdlib>
using namespace std; class myclass
{
public:
template<class T>
T add(T a)
{
return a;
} template<class T>
T add(T a,T b)
{
show(); //函数模板与类成员函数可以互相调用
return a + b;
} template<class T>
T add(T a, T b,T c)
{
return a + b + c;
} //template<class T>
//virtual T add(T a, T b,T c) //error C2898: “T myclass::add(T,T,T)”: 成员函数模板不能是虚拟的
//{
// return a + b + c;
//} void show()
{
cout << add<int>() << endl; //指明类型的方式调用
} }; int main()
{
myclass *p = nullptr;
p->add(, ); system("pause");
return ;
}
7. 类模板与函数模板对比:
#include <iostream>
#include <initializer_list>
#include <memory>
#include <string>
using namespace std; template<class T,int n>
class myarray
{
T *p;
public:
myarray(initializer_list<T> mylist)
{
p = new T[n]; //开辟内存
memset(p, , sizeof(T)*n); //内存清0 int length = mylist.size();
if (length > n)
{
abort(); //触发异常
}
else
{
int i = ;
for (auto j : mylist) //数据填充
{
p[i] = j;
i++;
}
}
} ~myarray()
{
delete[] p;
} void show() //显示数据
{
for (int i = ; i < n; i++)
{
cout << p[i] << " ";
}
cout << endl;
} void sort() //冒泡排序
{
for (int i = ; i < n - ; i++)
{
for (int j = ; j < n - - i; j++)
{
if (p[j] < p[j+]) //从大到小
{
T temp = p[j];
p[j] = p[j + ];
p[j + ] = temp;
}
}
}
}
}; int main()
{
myarray<int, > my1 = { ,,,,,,,, };
my1.show();
my1.sort();
my1.show(); myarray<double, > my2 = { 1.1,2.2,3.3,4.4,5.5 };
my2.show();
my2.sort();
my2.show(); myarray<string, > my3 = { "","abcdef","sdaf","hello" };
my3.show();
my3.sort();
my3.show(); system("pause");
return ;
}
8. 类包装器:
#include <iostream>
using namespace std; template<class T,class F> //函数模板
T run(T t, F f)
{
return f(t);
} class fun
{
public:
double operator ()(double data)
{
return data - ;
} }; template<class T> //类模板
class Tfun
{
public:
T operator ()(T data)
{
return data - ;
} }; int main()
{
cout << run(10.9, fun()) << endl; //fun()是匿名对象
fun x;
cout << run(10.9, x) << endl; //x是有名对象 cout << run(10.9, Tfun<double>()) << endl; //模板函数的匿名对象,构造函数返回的就是匿名对象
Tfun<double> fang;
cout << run(10.9, fang) << endl; system("pause");
return ;
}
9. 高级类包装器:
#include <iostream>
#include <list>
#include <vector>
using namespace std; template<class T, class F> //函数模板
T run(T t, F f)
{
return f(t);
} template<class T> //类模板
class Trun
{
public:
T operator ()(T data)
{
for (auto i:data)
{
cout << i <<" ";
}
cout << endl;
return data;
} }; int main()
{
list<int> myint; //构建链表,压入数据
for (int i = ; i < ; i++)
{
myint.push_back(i);
} run(myint, //lambda表达式
[](list<int> myint)->list<int>
{
for (auto i : myint)
{
cout << i << endl;
}
return myint;
}
); system("pause");
return ;
}
#include <iostream>
#include <list>
#include <vector>
using namespace std; template<class T, class F> //函数模板
T run(T t, F f)
{
return f(t);
} template<class T> //类模板
class Trun
{
public:
T operator ()(T data)
{
for (auto i:data)
{
cout << i <<" ";
}
cout << endl;
return data;
} }; int main()
{
vector<int> myv{ ,,,,,, };
run(myv, Trun< vector<int> >()); //匿名对象,用完就扔
run(myv, Trun< decltype(myv) >()); system("pause");
return ;
}
10. 类模板间的封装、继承、多态:
10.1 父类为类模板,子类也是类模板:
#include <iostream>
using namespace std; //类模板支持封装、继承、多态
template<class T>
class Tfu
{
public:
T t;
Tfu():t()
{
} void show()
{
cout << t << endl;
} virtual void go()
{
cout << "fu:" << t << endl;
}
}; template<class T>
class Tzi :public Tfu<T>
{
public:
void go()
{
cout << "zi:" << t << endl;
}
}; int main()
{
Tzi<int> tzi;
tzi.t = ;
tzi.show(); Tfu<int> *p = new Tzi<int>; //实现多态
p->go(); system("pause");
return ;
}
10.2 父类为类模板,子类为普通类:
#include <iostream>
using namespace std; template<class T>
class Tfu
{
public:
T t;
Tfu() :t()
{
} void show()
{
cout << t << endl;
} virtual void go()
{
cout << "fu:" << t << endl;
}
}; class zi :public Tfu<int>
{
public:
void go()
{
cout << "zi:" << t << endl;
}
}; int main()
{
zi z1;
z1.t = ;
z1.show(); Tfu<int> *p = new zi; //多态 此处只能用int
p->go(); system("pause");
return ;
}
10.3 父类为普通类,子类为类模板:
#include <iostream>
using namespace std; //类模板支持封装、继承、多态 //T T //类模板 可以实现封装、继承、多态
//T P //类模板与类 可以实现封装、继承、多态 必须明确类型
//P T //类与类模板 可以实现封装、继承、多态 必须明确类型 多态什么类型都可以
//P P //普通类 可以实现封装、继承、多态
class die
{
public:
int t;
die() :t()
{
} void show()
{
cout << t << endl;
} virtual void go()
{
cout << "fu: " << t << endl;
}
}; template<class T>
class er :public die
{
public:
void go()
{
cout << typeid(T).name() << " zi: " << t << endl;
} }; int main()
{
er<double> boer;
boer.show(); die *p1 = new er<char>;
die *p2 = new er<int>;
die *p3 = new er<double>;
p1->go();
p2->go();
p3->go(); system("pause");
return ;
}
3. STL编程三的更多相关文章
- C++ STL编程轻松入门基础
C++ STL编程轻松入门基础 1 初识STL:解答一些疑问 1.1 一个最关心的问题:什么是STL 1.2 追根溯源:STL的历史 1.3 千丝万缕的联系 1.4 STL的不同实现版本 2 牛刀小试 ...
- Linux网络编程(三)
Linux网络编程(三) wait()还是waitpid() Linux网络编程(二)存在客户端断开连接后,服务器端存在大量僵尸进程.这是由于服务器子进程终止后,发送SIGCHLD信号给父进程,而父进 ...
- Java并发编程三个性质:原子性、可见性、有序性
并发编程 并发程序要正确地执行,必须要保证其具备原子性.可见性以及有序性:只要有一个没有被保证,就有可能会导致程序运行不正确 线程不安全在编译.测试甚至上线使用时,并不一定能发现,因为受到当时的 ...
- 【读书笔记】.Net并行编程(三)---并行集合
为了让共享的数组,集合能够被多线程更新,我们现在(.net4.0之后)可以使用并发集合来实现这个功能.而System.Collections和System.Collections.Generic命名空 ...
- 【憩园】C#并发编程之异步编程(三)
写在前面 本篇是异步编程系列的第三篇,本来计划第三篇的内容是介绍异步编程中常用的几个方法,但是前两篇写出来后,身边的朋友总是会有其他问题,所以决定再续写一篇,作为异步编程(一)和异步编程(二)的补 ...
- C++ STL编程轻松入门【转载】
1 初识STL:解答一些疑问 1.1 一个最关心的问题:什么是STL "什么是STL?",假如你对STL还知之甚少,那么我想,你一定很想知道这个问题的答案,坦率地讲,要指望用短短数 ...
- C++面向对象高级编程(三)基础篇
技术在于交流.沟通,转载请注明出处并保持作品的完整性. 概要 一.拷贝构造 二.拷贝赋值 三.重写操作符 四.生命周期 本节主要介绍 Big Three 即析构函数,拷贝构造函数,赋值拷贝函数,前面主 ...
- OpenGL ES2.0编程三步曲 -转
原地址:http://blog.csdn.net/myarrow/article/details/7707943 1. 保存全局变量的数据结构 以下例子程序均基于Linux平台. typedef st ...
- STL编程:C++的忠告!
Copy别人的,有少量修改,可以做为一下参考! C++之父Bjarne Stroustrup 写的 The C++ Programming Language (Special Edition) 中各章 ...
随机推荐
- [转] 移动平台Html5的viewport使用经验
转自:http://blog.csdn.net/wuruixn/article/details/8591989 问题描述 web页面采用html5技术实现,在系统登录页面中使用frameset.fra ...
- 多线程中,ResultSet为空,报错空指针
最近在数据库查询数据时,由于数据量太大,使用了多线程,通过线程池建了好几个线程,然后调用了一个封装好的jdbc查询语句. 结果在多线程中,ResultSet报错空指针. 仔细查阅后,才发现多个线程访问 ...
- HTTP请求出现405状态码method not allowed的解决办法
httppost请求目标网站出现405状态码, 原因为 Apache.Nginx.IIS等绝大多数web服务器,都不允许静态文件响应POST请求所以将post请求改为get请求即可
- 78. Subsets (Back-Track, DP)
Given a set of distinct integers, nums, return all possible subsets. Note: Elements in a subset must ...
- input和React-Native的TextInput的输入限制,只能输入两位小数(阻止0开头的输入),类似价格限制
一.背景: 想要实现一功能: 1. 最多只能输入两位小数,类似的价格限制 2. 实时监听限制输入,禁止输入不符合规范的字符(当输入违禁字符,进行删除操作) 这样做的优点: 1. 在用户输入时直接进行限 ...
- Under-sampling
Under sampling When the signal frequency is high, and the tester frequency can’t catch the signal ...
- mongo学习- mapReduce操作事例
源数据: { "_id" : 1.0, "name" : "abc", "age" : 43.0, "type ...
- rabbitmq用户权限管理
原文地址: http://my.oschina.net/hncscwc/blog/262246 安装最新版本的rabbitmq(3.3.1),并启用management plugin后,使用默认的账号 ...
- windows平台下spark-shell配置
一.下载安装spark,http://spark.apache.org/,选择合适版本后下载到本地,解压,bin目录下spark-shell文件就是spark命令行交互的入口. 二.下载安装windo ...
- Gym 101201J Shopping (线段树+取模)
题意:给定 n 个物品,然后有 m 个人买东西,他们有 x 元钱,然后从 l - r 这个区间内买东西,对于每个物品都尽可能多的买,问你最少剩下多少钱. 析:对于物品,尽可能多的买的意思就是对这个物品 ...