p167 模板-模板的概念
p168 函数模板基本语法
使用模板函数的第一种方式:自动类型推导
第二种方式:显示指定类型
#include <iostream>
using namespace std;
//模板的使用
//函数模板
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
template<typename T>
void mySwap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
void test01()
{
int a = 10, b = 25;
//第一种使用模板函数的方式
//自动类型推导
// mySwap(a, b);
//第二种:显示指定类型
mySwap<int>(a, b);
cout << a << endl;
cout << b << endl;
}
int main()
{
test01();
return 0;
}
函数模板的用途或者意义:将类型参数化,首先将类型抽象化(变成一个通用的类型),然后使用的时候传入参数也就是相关类型就可以了
提高复用性,将类型参数化也就是抽象化
p169 函数模板注意事项
p170 函数模板案例
案例:
#include <iostream>
using namespace std;
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
template<typename T>
void mySwap(T &a, T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
//排序算法 函数模板2
template<class T>
void mySort(T arr[],int len)
{
//使用选择排序的算法进行从小到大排序
for (int i = 0; i < len;i++)
{
int max = i;//认定最大值的下标
for (int j = i + 1; j < len;j++)
{
//认定的最大值 比遍历出的最大值要小,说明小标j的元素才是真正的最大值
if (arr[max]<arr[j])
{
max = j;
}
}
if(max!=i)
{
mySwap(arr[max], arr[i]);
}
}
}
//提供打印数组的模板3
template<class T>
void printArr(T &arr,int len)
{
for (int i = 0; i < len;i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void test01()
{
//测试char数组
char charArr[] = "badcef";
int num = sizeof(charArr) / sizeof(char);
mySort(charArr,num);
printArr(charArr, num);
//测试int数组
int intArr[] = {1, 2, 5, 9, 24, 78};
num = sizeof(intArr) / sizeof(int);
mySort(intArr,num);
printArr(intArr, num);
}
int main()
{
test01();
return 0;
}
p171 普通函数与函数模板的区别
#include <iostream>
using namespace std;
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
template<class T>
T myAdd(T a, T b)
{
return a + b;
}
void test01()
{
int a = 10, b = 25;
char c = 'c';//ASCII c=97
// cout << myAdd(a, c) << endl;//错误的写法 不会自己隐世类型转化
cout << myAdd<int>(a, c) << endl;//这种情况会自动类型推导
}
int main()
{
test01();
return 0;
}
p172 普通函数和函数模板调用规则
四条调用规则:
来调用函数模板
第四条规则:
我们要防止二义性::
p173 模板的局限性
#include <iostream>
using namespace std;
#include <string>
//模板的使用
class Person
{
public:
Person(int age,string name)
{
m_Age = age;
m_Name = name;
}
int m_Age;
string m_Name;
};
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
template<class T>
bool myCompare(T &a, T &b)
{
if(a==b)
{
return true;
}
else
{
return false;
}
}
//利用具体化Person的版本实现代码 具体化优先调用
//前面的template<> 告诉我们这是一个具体化的函数模板
template<> bool myCompare(Person &p1, Person &p2)
{
if (p1.m_Age==p2.m_Age && p1.m_Name==p2.m_Name)
{
return true;
}
else
{
return false;
}
}
void test01()
{
int a = 10, b = 25;
cout << myCompare(a, b) << endl;
Person p1(18, "tom");
Person p2(18, "tom");
cout << myCompare(p1, p2) << endl;
}
int main()
{
test01();
return 0;
}
p174 类模板的基本用法
#include <iostream>
using namespace std;
#include <string>
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
//类模板
template<class Nametype,class Agetype>
class Person
{
public:
Person(Nametype name, Agetype age)
{
m_Name = name;
m_Age = age;
}
void show()
{
cout << m_Name << endl;
cout << m_Age << endl;
}
Nametype m_Name;
Agetype m_Age;
};
void test01()
{
Person<string, int> p1("sunwukong", 85);
p1.show();
}
int main()
{
test01();
return 0;
}
this指针
总结:
p175 类模板与函数模板区别
模板的参数列表可以有默认参数的
p176 类模板中成员函数创建时机
类模板中的成员函数一开始不会创建出来,只有调用的时候才会创建出来
类模板中的成员函数一开始不会创建出来,只有调用的时候才会创建出来
类模板中的成员函数一开始不会创建出来,只有调用的时候才会创建出来
类模板中的成员函数一开始不会创建出来,只有调用的时候才会创建出来
类模板中的成员函数一开始不会创建出来,只有调用的时候才会创建出来
#include <iostream>
using namespace std;
#include <string>
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
//类模板
class Person1
{
public:
void showPerson1()
{
cout << "showPerson1" << endl;
}
};
class Person2
{
public:
void showPerson2()
{
cout << "show Person2" << endl;
}
};
template<class T>
class myClass
{
public:
T obj;
void func1()
{
obj.showPerson1();
}
void func2()
{
obj.showPerson2();
}
};
void test01()
{
myClass<Person1> p1;
p1.func1();
myClass<Person2> p2;
p2.func2();
}
int main()
{
test01();
return 0;
}
p177 类模板对象作函数参数
类模板也是可以实例化对象的
类模板也是可以实例化对象的
类模板也是可以实例化对象的
类模板也是可以实例化对象的
三种类型
第二种 第三种就是函数模板配合着类模板
第二种 第三种就是函数模板配合着类模板
第二种 第三种就是函数模板配合着类模板
#include <iostream>
using namespace std;
#include <string>
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
//类模板
template<class T1, class T2>
class Person
{
public:
Person(T1 name, T2 age)
{
m_Name = name;
m_Age = age;
}
void showPerson()
{
cout << m_Name << endl;
cout << m_Age << endl;
}
T1 m_Name;
T2 m_Age;
};
//1.指定传入类型
void printPerson1(Person<string, int> &p)
{
p.showPerson();
}
//2.参数模板化 也就是函数模板
template<class T1, class T2>
void printPerson2(Person<T1,T2> &p)
{
p.showPerson();
}
//3.整个类参数化 也就是函数模板
template<class T>
void printPerson3(T &p)
{
p.showPerson();
}
void test01()
{
Person<string, int> p("孙悟空", 185);
printPerson1(p);
Person<string, int> p2("孙悟45空", 185);
printPerson2(p2);
Person<string, int> p3("孙悟4445空", 85);
printPerson3(p3);
}
int main()
{
test01();
return 0;
}
p178 类模板与继承
类模板
灵活指定父类中的T类型
这样
p179 类模板成员函数类外实现
成员函数在类内申明,类外进行实现
类模板的类外实现
<>体现出模板
#include <iostream>
using namespace std;
#include <string>
//模板的使用
//函数模板1
//声明一个模板,告诉编译器后面的代码中紧跟着的T不要报错,T是一个通用的数据类型
//typename也可以用class 后面的一般用T
//类模板
template<class T1,class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
//类模板成员函数的类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
m_Age = age;
m_Name = name;
}
template<class T1, class T2>
void Person<T1,T2>::showPerson()
{
cout << m_Name << " " << m_Age << endl;
}
void test01()
{
Person<string,int> p1("zhangshuai", 22);
p1.showPerson();
}
int main()
{
test01();
return 0;
}
p180 类模板分文件编写
如果类很多的话,.h文件中放类的声明,.cpp放类的具体实现
主函数部分:
#include <iostream>
#include "Person.h"//可加可不加 因为下一句调用时 person.cpp文件中有person.h
#include "Person.cpp"
using namespace std;
void test01()
{
Person<string,int> p1("zhangshuai", 22);
p1.showPerson();
}
int main()
{
test01();
return 0;
}
#include "Person.h"
//类模板成员函数的类外实现
template<class T1,class T2>
Person<T1,T2>::Person(T1 name, T2 age)
{
m_Age = age;
m_Name = name;
}
template<class T1, class T2>
void Person<T1,T2>::showPerson()
{
cout << m_Name << " " << m_Age << endl;
}
//防止头文件重复包含
#pragma once
#include <iostream>
using namespace std;
#include <string>
//类模板
template<class T1,class T2>
class Person
{
public:
Person(T1 name, T2 age);
void showPerson();
T1 m_Name;
T2 m_Age;
};
p181-p184 暂时未学习
p185 STL初识-STL的基本概念
C++面向对象的三大特性:封装 继承 多态
仿函数就是重载的小括号,其行为非常类似函数的调用 故称为仿函数
算法通过迭代器才可以访问容器中的数据
算法通过迭代器才可以访问容器中的数据
算法通过迭代器才可以访问容器中的数据
迭代器使用类似于指针
迭代器使用类似于指针
迭代器使用类似于指针
迭代器使用类似于指针
迭代器使用类似于指针
迭代器使用类似于指针
p186 vector存放内置数据类型
利用了一下回调技术
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
//回调函数
void MyPrint(int val)
{
cout << val << endl;
}
void test01()
{
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
vector<int>::iterator pBegin = v.begin();
vector<int>::iterator pEnd = v.end();
for_each(v.begin(), v.end(), MyPrint);
}
int main()
{
test01();
}
p187 vector容器存放自定义数据类型
每个容器都有自己专属的迭代器
it的数据类型 看尖括号里面的类型,it是一个迭代器对象 有点类似于指针
it的数据类型 看尖括号里面的类型,it是一个迭代器对象 有点类似于指针
it的数据类型 看尖括号里面的类型,it是一个迭代器对象 有点类似于指针
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
class Person
{
public:
Person(string name,int age)
{
m_Name = name;
m_Age = age;
}
string m_Name;
int m_Age;
};
//存放对象
void test01()
{
vector<Person> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
Person p5("eee", 50);
Person p6("fff", 60);
v.push_back(p1);
v.push_back(p2);
v.push_back(p3);
v.push_back(p4);
v.push_back(p5);
v.push_back(p6);
for (vector<Person>::iterator it = v.begin(); it != v.end();it++)
{
cout << "name:" << it->m_Name
<< "age:" << it->m_Age << endl;
}
}
void test02()
{
vector<Person*> v;
Person p1("aaa", 10);
Person p2("bbb", 20);
Person p3("ccc", 30);
Person p4("ddd", 40);
Person p5("eee", 50);
Person p6("fff", 60);
v.push_back(&p1);
v.push_back(&p2);
v.push_back(&p3);
v.push_back(&p4);
v.push_back(&p5);
v.push_back(&p6);
//这里*it的数据类似是 Person *
for (vector<Person *>::iterator it = v.begin(); it != v.end();it++)
{
cout << "name: " << (*it)->m_Name
<< "age: " << (*it)->m_Age << endl;
}
}
int main()
{
test02();
}
这里*it的数据类似是 Person *
迭代器对象的使用非常类似于指针
迭代器对象的使用非常类似于指针
迭代器对象的使用非常类似于指针
迭代器对象的使用非常类似于指针
迭代器对象的使用非常类似于指针
p188 容器嵌套容器
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
//容器嵌套容器
void test01()
{
//容器
vector<vector<int>> v;
vector<int> v1;
vector<int> v2;
vector<int> v3;
vector<int> v4;
//向小容器中添加数据
for (int i = 0; i < 3;i++)
{
v1.push_back(i);
v2.push_back(i+1);
v3.push_back(i+2);
v4.push_back(i+3);
}
//将小容器插入到大容器中
v.push_back(v1);
v.push_back(v2);
v.push_back(v3);
v.push_back(v4);
//通过大容器,遍历所有数据
for (vector<vector<int>>::iterator it = v.begin();
it != v.end(); it++)
{
for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end();vit++)
{
cout << *vit << " ";
}
cout << endl;
}
}
int main()
{
test01();
}
vector有点类似于数组,容器嵌套容器有点类似二维数组的感觉。
p189 string容器 构造函数
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
//容器嵌套容器
void test01()
{
string s1;//默认构造函数 创建空字符串
const char *str = "hjexsd";
string s2(str);
string s3(s2);
cout << s2 << endl;
cout << s3 << endl;
string s4(10, 'a');
cout << s4 << endl;
}
int main()
{
test01();
}
p190 赋值操作
p191 string字符串拼接
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
//容器嵌套容器
void test01()
{
string str1 = "我";
str1 += "爱玩游戏";
str1 += ':';
cout << str1 << endl;
string str2 = "lol";
str1 += str2;
cout << str1 << endl;
str1.append(" sssss");
cout << str1 << endl;
str1.append("zhangshuai",0,3);
cout << str1 << endl;
}
int main()
{
test01();
}
p197 vector容器-构造函数
stl模板类
p198 vector容器赋值操作
p199 容量和大小
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;//默认构造 也就是无参构造
for (int i = 1; i < 10;i++)
{
v1.push_back(i);
}
printVector(v1);
if (v1.empty())
{
cout << "空" << endl;
}
else
{
cout << "不为空" << endl;
cout << "v1的容量" << v1.capacity() << endl;
cout << "v1的大小" << v1.size() << endl;
}
//重新指定大小
v1.resize(15,12);
printVector(v1);
}
int main()
{
test01();
}
p200 vector容器插入和删除
每个容器都有专属于自己的迭代期
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;//默认构造 也就是无参构造
for (int i = 1; i < 5;i++)
{
v1.push_back(i);
}
printVector(v1);
//提供的一些成员函数
cout << v1.at(2) << endl;
cout << v1[2] << endl;
cout << v1.front() << endl;
cout << v1.back() << endl;
}
int main()
{
test01();
}
vector互换容器
匿名对象有个特点 所在行执行完之后,被系统回收
匿名对象有个特点 所在行执行完之后,被系统回收
匿名对象有个特点 所在行执行完之后,被系统回收
收缩内存的效果
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
using namespace std;
void printVector(vector<int> &v)
{
for (vector<int>::iterator it = v.begin(); it != v.end();it++)
{
cout << *it << " ";
}
cout << endl;
}
void test01()
{
vector<int> v1;//默认构造 也就是无参构造
for (int i = 1; i < 5;i++)
{
v1.push_back(i);
}
printVector(v1);
//提供的一些成员函数
vector<int> v2;
for (int i = 5; i > 0;i--)
{
v2.push_back(i);
}
printVector(v2);
v2.swap(v1);
printVector(v1);
printVector(v2);
cout << v1.size() << " " << v1.capacity() << endl;
v1.resize(3);
printVector(v1);
cout << v1.size() << " " << v1.capacity() << endl;
vector<int>(v1).swap(v1);
cout << v1.size() << " " << v1.capacity() << endl;
}
int main()
{
test01();
}