仿函数是一个类,里面有成员函数重载()符号,在我们调用实例对象的时候,会自动调用重载函数,这样就像是一个函数一样
myadd(10,10)
public:
int operator()(int v1, int v2)
{
return v1+v2
}
最上面的一个实例对象,传入两个参数之后,就会自动调用成员函数重载()
重载函数接受一个参数就叫做一元谓词,接受两个参数就叫做二元谓词
内建函数
在库里面将一封装一些仿函数,我们可以在加入库的头文件之后,就可以像函数一样使用他们
模板与我们的一般其实差不多,就是一个特点这个函数的传入参数可以是动态变化的,因此我们要在模板开头写一句声明特殊的数据类型
template
template
函数声明或定义
template —表示声明创建出一个模板
typename —表示后面是一个数据类型,我们也可以写成class
T ------通用的数据类型,名称可以替换,一般是大写字母
我们在数据传入的时候有两种方式
1、自动类型推导(数据本身的数据类型)
2、显示指定类型(标出传入数据的类型)
/利用模板函数兼容上面两个函数
template //类模板的声明
template //类模板的声明//创建一个类模板函数
void myswap(T& a, T& b)
{T temp = a;a = b;b = temp;
}
模板的实例化
编译器就通过这个模板,推出一个 T 是 int 类型的函数。
这时编译器就把这个模板里的 T 都替换成 int,生成出一份 T 是 int 的函数,传入的类型不同生成的函数也是不同的


我们的a1是int d1是double类型,在传参之前会强制转为double
显示类型转换

模板函数的匹配
函数模板与普通函数同名的话,优先调用普通函数
在实验空模板列表参数就会优先调用函数模板
myPrint<>(a,b);
模板的局限性:我们自定义的数据结构需要将模板函数重载之后才可以使用,不然无法识别自定义的数据类型
类模板(只支持显示类型推导)
template< typename T>——声明创建模板,多个变量要写成下面的形式
typename——表明其后面的符号是一种数据类型,可以用class代替
T——通用的数据类型,名称可以替换,通常为大写字母
//类模板
template
class Person
{
public:Person(NameType name, AgeType age){this->m_Age = age;this->m_Name = name;}void showPerson(){cout << this->m_Name << this->m_Age << endl;}NameType m_Name;AgeType m_Age;
};
类模板对象做函数参数
指定传入的类型——直接显式对象的数据类型(没有隐式类型转换)

参数模板化——将对象中的参数变为模板参数进行传递

整个类模板化——将这个对象类型,模板化进行传递

子类在基础一个父类模板的时候,我们必须要指定父类的数据类型,不然无法继承

类模板的成员函数类外实现
1、写类模板,成员函数只有定义,没有具体内容

2、类外实现
类模板中函数放在类外进行定义时,需要加模板参数列表

类模板分文件编写
就是将我们的预定于类与我们的类外定义写在一个文件中,后缀交hpp
一般我们类中的私有部分是外界成员无法访问的,但是要是在类中声明一个外界函数或者类时这个类的友元,那么这个外界函数或者类就可以访问到类的私有部分
友元是单向的(单向好友)
我们将外部函数声明了友元之后,函数指针buildding就可以访问到类的私有部分了
#include
#include using namespace std;// 房屋类
class Building
{// 告诉编译器 laoWang全局函数是 Building类 的好朋友,可以访问Building对象的私有成员friend void laoWang1(Building *building);friend void laoWang2(Building &building);friend void laoWang3(Building building);public:Building(){m_SittingRoom = "客厅";m_BedRoom = "卧室";}string m_SittingRoom; // 客厅private:string m_BedRoom; // 卧室
};//全局函数
void laoWang1(Building *building)
{cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(地址传递) " << building->m_BedRoom << endl;
}void laoWang2(Building &building)
{cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:(引用传递) " << building.m_BedRoom << endl;
}void laoWang3(Building building)
{cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_SittingRoom << endl;cout << "隔壁老王 全局函数 正在访问:( 值传递 ) " << building.m_BedRoom << endl;
}void test()
{Building building;laoWang1(&building);laoWang2(building);laoWang3(building);
}int main()
{test();
}
声明类的友元之后,友元类就可以调用这个类私有成员
#include
#include using namespace std;// 类作友元class Building;
class LaoWang
{
public:LaoWang();void visit(); //参观函数 访问Building中的属性Building * building;private:};// 房屋类
class Building
{// 告诉编译器,LaoWang类是Building类的好朋友,可以访问Building类的私有成员friend class LaoWang;
public:Building();string m_SittingRoom; // 客厅private:string m_BedRoom; // 卧室
};// 类外定义成员函数Building::Building()
{m_SittingRoom = "客厅";m_BedRoom = "卧室";
}LaoWang::LaoWang()
{// 创建建筑物对象building = new Building;
}void LaoWang::visit()
{cout << "隔壁老王LaoWang类正在访问:" << building->m_SittingRoom << endl;cout << "隔壁老王LaoWang类正在访问:" << building->m_BedRoom << endl;
}void test()
{LaoWang lw;lw.visit();
}int main()
{test();return 0;
}