1、仿函数与谓词与内建函数
仿函数是一个类,里面有成员函数重载()符号,在我们调用实例对象的时候,会自动调用重载函数,这样就像是一个函数一样
myadd(10,10)
public:
int operator()(int v1, int v2)
{
return v1+v2
}
最上面的一个实例对象,传入两个参数之后,就会自动调用成员函数重载()
重载函数接受一个参数就叫做一元谓词,接受两个参数就叫做二元谓词
内建函数
在库里面将一封装一些仿函数,我们可以在加入库的头文件之后,就可以像函数一样使用他们
2、函数模板与类模板
模板与我们的一般其实差不多,就是一个特点这个函数的传入参数可以是动态变化的,因此我们要在模板开头写一句声明特殊的数据类型
template
template
函数声明或定义
template —表示声明创建出一个模板
typename —表示后面是一个数据类型,我们也可以写成class
T ------通用的数据类型,名称可以替换,一般是大写字母
我们在数据传入的时候有两种方式
1、自动类型推导(数据本身的数据类型)
2、显示指定类型(标出传入数据的类型)
/利用模板函数兼容上面两个函数
template //类模板的声明
template<typename T > //类模板的声明
//创建一个类模板函数
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 NameType,class AgeType>
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
3、友元
一般我们类中的私有部分是外界成员无法访问的,但是要是在类中声明一个外界函数或者类时这个类的友元,那么这个外界函数或者类就可以访问到类的私有部分
友元是单向的(单向好友)
1、友元函数
我们将外部函数声明了友元之后,函数指针buildding就可以访问到类的私有部分了
#include <iostream>
#include <string>
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();
}
2、友元类
声明类的友元之后,友元类就可以调用这个类私有成员
#include <iostream>
#include <string>
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;
}