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) 中各章 ...
随机推荐
- 138. Copy List with Random Pointer (Graph, Map; DFS)
A linked list is given such that each node contains an additional random pointer which could point t ...
- 使用C#进行基于PI的开发
首先欲基于PI-SDK开发PI数据库,必须先安装PI-SDK,然后再VS中新建了一个aspnet网站,添加引用:PI-SDK 1.2 Type Library 和 PISDKCommon 1.2 Ty ...
- php从数组中取出一段 之 array_slice
array array_slice ( array $array , int $offset [, int $length [, bool $preserve_keys ]] ) array_slic ...
- RNA -seq
RNA -seq RNA-seq目的.用处::可以帮助我们了解,各种比较条件下,所有基因的表达情况的差异. 比如:正常组织和肿瘤组织的之间的差异:检测药物治疗前后,基因表达的差异:检测发育过程中,不同 ...
- 谈谈WhatsApp一年设计经历和收获
以下内容由Mockplus团队翻译整理,仅供学习交流,Mockplus是更快更简单的原型设计工具. 关于WhatApp和Facebook如何实现规模设计的思考 我已经在Facebook担任产品经理 ...
- linux每天一小步---tail命令详解
1 命令功能 tail命令用于显示文件中末尾的内容(默认显示最后10行内容) 2 命令语法 tail [选项参数] [文件名1] [文件名2] 3 命令参数 -f 用于循环读取文件的内容,监视文件的 ...
- Java动态代理(二)CGLIB动态代理应用
JDK自从1.3版本开始,就引入了动态代理,JDK的动态代理用起来非常简单,但是它有一个限制,就是使用动态代理的对象必须实现一个或多个接口 .如果想代理没有实现接口的类可以使用CGLIB包. CGLI ...
- tomcat启动时就频繁gc和full gc
一个小业务,流量并不大,功能也很简单,spring framework+mybatis+quartz,一启动就看到gc的频次和full gc的频次非常高: 4.202: [Full GC 4.202: ...
- 由于没有公钥,无法验证下列签名 Ubuntu
问题:执行 apt-get update 时错误 W: GPG 错误:https://apt.dockerproject.org ubuntu-trusty InRelease: 由于没有公钥,无法验 ...
- MVP社区巡讲 12月5日北京站| 12月12日上海站
2015年底的社区巡讲Powered MVP Roadshow正式启动啦!12月5日周六下午北京场,12月12日周六下午上海场. 欢迎各位邀请您的同事朋友来参加MVP的社区活动,也邀请您发送活动信息( ...