C++日记——Day23:typename的使用场合、函数指针做其他函数的参数、可调用对象、默认模板参数

typename使用场合

1、在模板定义里表明气候的参数是类型参数

//函数模板
template<typename T, int a, int b>
int funcadd(T c) { };

//类模板
template<typename T, int b>
class myvector {  };

注意这里的typename可以写成class

 

2、使用类的类型成员,用typename标志这是一个类型。

::作用域运算符 :1、访问类的静态函数成员   2、访问类型成员myiterator(是一个由typedef定义的类型)

//迭代器
template<typename T>
typename myvector<T>::myiterator myvector<T>::mybegin() 
//这里的typename是必须的,如果不加typename编译器会将myvector<T>::myiterator当成是一个静态数据成员
{

}

 这里typename是必须的,告诉编译器,这个名字是一个类型,这里的typename不能换成class

template<typename T>
typename T::size_type getlength(const T &c)
{

}

string::size_type size = getlength(mytest);

当使用类型模板参数   T::类型成员(<T>::类型成员)  时,前面都要加typename

 

函数指针做其他函数的参数

函数指针要当做函数的参数时: 

typedef int(*FunType)(int, int);

用 typedef 相当于定义了一个函数指针类型,定义类型时必须用typedef

void testfunc(int i, int j, FunType funcpoint)
{
    funcpoint(i, j);//相当于调用函数,funcpoint
}

mf(int i, int j)
{
    int result = i + j;
}



int main()
{
    testfunc(1 ,2, mf);

}

 

特殊写法

template<typename T, typename F>
void testfunc(const T &i, const T &j, F funcpoint)
{
    cout << funcpoint << endl;
}

class TC
{
public:
    void opreator() const
    {
    }
}

int main()
{    
    TC tc1;
    void (*funcp)();
    testfunc(1, 2, funcp);
    testfunc(1, 2, tc1);
    testfunc(1, 2, TC());
}

 

可调用对象

圆括号就是函数调用的标记,()有一个称呼叫做“函数调用运算符”

如果在类中重载函数调用运算符,那么就可以想使用函数一样使用该类对象。对象(实参);

class biggerthanzero
{
public:
    biggerthanzero(int u)
    {
        
    }
public:
    int operator()(int value) const //const非必须,根据是否需要改变类成员而定
    {
        if (value < 0) return 0;
        return value;
    }

    int operator()(int value1, int value2) const //const非必须,根据是否需要改变类成员而定
    {
        if (value < 0) return 0;
        return value;
    }
}


int main()
{
    biggerthanzero obj(2); //这里实在执行对象初始化
    int result = obj(100); //这里调用重载()运算符
    int result = obj.operator()(200);
}

 

如何使用函数调用运算符

1、定义一个该类对象。

2、像函数一样使用该对象,也就是()中增加实参列表。

结论:只要这个对象所属的类重载了()“函数调用运算符”,那么这个类对象就变成了可调用的了,而且可以调用多个版本的(),只要在参数的类型和数量上有差别。

这个类重载了(),该类的对象就多了个名字,“函数对象”,因为可以调用这种对象,或者说这些对象可以像函数一样被调用。

 

不同对象的相同调用形式

int echovalue(int value)
{
    if (value < 0) return 0;
    return value;
}

函数echovalue和 biggerthanzero重载的(),这两个东西,调用参数和返回值相同,就叫做“调用形式相同”。

一种调用形式 对应 一个函数类型:int(int)

1、echovalue函数。

2、重载了函数调用运算符的biggerthanzero类对象。

把这些可调用对象指针保存起来,目的是方便我们随时调用这些可调用对象。这个感觉像C语言的函数指针

map<string, int(*)(int)> myoper;

myoper.insert({"ev", echovalue});
myoper.insert({"ev", obj}); //报错,说明编译器没有把这个类对象看成是一个函数

 

标准库function

function模板:要提供模板参数来表示该function类型能够表示的对象的调用形式。

#include <function>
function<int(int)> //声明了一个function()类型,用来代表一个可调用对象,它所代表的这 
                   //个可调用对象是:接受一个int型参数并返回int类型。

function<int(int)> f1 = echovalue; //可以,放函数指针
function<int(int)> f2 = obj;  //可以,放类对象
function<int(int)> f3 = biggerthanzero(); //直接放类对象也可以

f1(2);
f2(2);
f3(2);
map<string, func<int(int)>> myoper = {
    {"ev", echovalue},
    {"obj1", obj}
}

myoper["ev"](12); //调用函数

如果echovalue有重载就无法放倒function<>中 

我们可以通过定义函数指针来解决。

int (*fp)(int) = echovalue;
function<int(int)> f1 = fp;

 

默认模板参数

1、类模板,类模板名后边必须提供额外信息。<>表示这是一个模板;默认值参数规则与函数的参数列表默认值书写规则一致 

2、函数模板,老标准只能为类模板提供默认参数,C++11可以为函数模板提供默认参数。

template<typename T, typename F=TC>
void testfunc(const T &i, const T &j, F funcpoint = F())
{
    cout << funcpoint(i, j) << endl;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值