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) 中各章 ...
随机推荐
- java多线程通信方式之一:wait/notify
java多线程之间的通信方式有多种: 1.wait(),notify(),notifyAll()方法;2.join()方法;3.通过volatile共享内存的方式进行线程通信的;4.interrupt ...
- flume 配置说明
Flume中的HDFS Sink应该是非常常用的,其中的配置参数也比较多,在这里记录备忘一下. channel type hdfs path 写入hdfs的路径,需要包含文件系统标识,比如:hdfs: ...
- input实时监听控制输入框的输入内容和长度,并进行提示和反馈
一.前言 在MVVM模式下,有个双向数据绑定(data-binding)的优势,可以通过viewmodel实时的监听用户操作,也可以将model的改动实时的反馈到界面上. 那么,在传统的js操控DOM ...
- windows 安装git
搭建环境:windo server 2012 方案: 服务器端:gitblit.下载地址:http://www.gitblit.com/ 客户端:git for windows.下载地址:https: ...
- 39-python 字符串替换+正则
from bs4 import BeautifulSoup import urllib.request import re moduel =re.compile('<.*?>') st = ...
- Mybatis框架的输出映射类型
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. resultType(输出类型) 1.输出简单类型 (1)我们在UserM ...
- windows 7 64 bit 注册dll
手动需要run as admin, 也可以用下边的脚本自动注册 @echo off setlocal enableextensions set REGSVR= if defined PROCESSOR ...
- Golang之实现(链表)
链表算法 package main import "fmt" type LinkNode struct { data interface{} next *LinkNode } ty ...
- BI实施的四个层次
满足业务需求 注重数据分析汇总 统一.高效的系统集成越来越麻烦.管理人员穿梭在具有不同风格.使用逻辑的系统间,越来越厌倦,众多系统之间的业务逻辑.数据含义不一致,使用户无法判 断数据的准确性.任何一个 ...
- Monokai风格的EditPlus配色方案
EditPlus的配置文件editplus_u.ini,该文件默认在:系统盘:\Users\用户名\AppData\Roaming\EditPlus目录中.将其中的内容替换为如下即可: [Option ...