您的位置:首页 > 编程语言 > C语言/C++

c++重载与模板

2016-07-12 19:48 225 查看
   一、 模板是泛型编程的重要支持,函数和类模板在STL中运用的非常广泛,首先谈谈c中的函数重载和c++中的函数模板的区别:

1、首先,函数重载是函数名相同,但参数个数和类别不同,如果增加参数个数和参数型别就要重新编写相应的重载函数,而相对于函数模板就比较灵活,我们只要编写一个函数模板,编译器在编译是就会根据参数类型特例化出相应的版本,而且模板支持可变参数(template<class T,class ... Args>,..代表0个或多个参数);

2、重载函数需要注意作用域问题:

class base
{
public:
void fun(void)
{
cout<<"base::fun()"<<endl;
}

};
class derived :public base
{
public:
int fun(int a)
{
cout<<"derived::fun(int)"<<endl;
}
};
如上,我们在基类定义了一个返回和参数都为空的fun函数,而在派生类中又定义了返回和参数都为int型的函数fun,按我们常规的思维会认为我们对fun函数进行了重载,其实不然,由于两者函数名相同,在继承过程中派生类的函数会覆盖基类的函数,所以我们只重载了int 型的函数,所以重载会有作用域的问题;而模板函数相对就方便多了,只要在模板的可见范围内,我们就可以通过一个模板实例化多个函数。

二、函数模板的匹配规则

1、如果只有一个匹配函数,就选择该函数

2、如果同样好的匹配函数中只有一个是非模板函数,就选择该非模板函数

3、如果同样好的函数中没有非模板函数,而有多个函数模板,且其中一个模板比其他模板更特例化,选择更特例化的版本(偏特化:偏特化只能适用于类模板,不能用于函数模板)

4、否则有歧义,编译出错。

   总之,编译器总是选择更特殊和可能出现类型转换代价更少(可能会出现非常量向常量的自动转换的过程)的那个版本,总之电脑比较“笨”和“懒”,你给的信息越多、操作代价越少,编译器就会毫不犹豫选择该版本。

三、 可变参数模板和sizeof...运算符

    可变参数模板就是一个接受可变数目参数的模板函数或模板类,存在两两个参数包:模板参数包和函数参数包:

<span style="font-size:14px;">template<typname T,typename...Args>  //Args是模板参数

void foo(const T&t,const Args& ... rest)  //rest是函数参数
{
cout<<sizeof...(rest)<<endl;   </span><pre name="code" class="cpp"><span style="font-size:14px;">    cout<<sizeof...(Args)<<endl;  //得到参数的个数</span>

}


四、函数模板和重载决议中的易错点

     特别注意:函数特例化的本质是实例化一个模板,而非重载它,所以特例化的版本不影响函数匹配:

template<typename T> void f(T);/* a */
template<typename T> void f(T*);/* b */
template< > void f<int>(int*);/* c */
int* p;
f(p);     //1、调用上面拿个版本???

template<typename T> void f(T);/* a */
template< > void f<int*>(int*);/* b */
template<typename T> void f(T*);/* c */
int* p;
f(p);     //2、这里又调用哪个版本?
分析:

对于第一个代码块,a是一个模板,b也是一个模板,c只是b的一个全特化(template<> 指出我们正在实例化一个模板,还是一个模板,不是非模板),我呢吧将一个特殊的函数定义为一个特例化版本还是一个独立的非模板函数,会影响到函数匹配,所以函数的匹配原则是:只在模板和非模板之间匹配,模板的偏特化和特化版本不参与最初的函数匹配,只有选择了匹配了该函数模板后才会考虑该模板下的特化版本!!!

所以对于第一题,由于c是b的特化,因此现在a,b中匹配,因为p是指针,所以b匹配效果要好,所以选择了b,但编译器发现已经有了完全匹配的c版本,所以就不再特例化一个版本,因此最后选择了c这个版本的函数模板。

对于第二题:b是a的特化版本,先在a,c中匹配,发现c的匹配效果更好,而c没有特例化版本,就直接选择c(虽然b的匹配完全符合,但它完全没有得到匹配的资格就gameover了);

上面的问题是一个非常容易错的问题!!!应重视!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: