函数模板
泛型编程
泛型编程,顾名思义就是与实际类型无关的一种编程模式,属于代码复用的一种手段。为了提高开发效率和代码的泛化能力,泛型编程被广泛应用与日常的开发工作中,而其也成为了开发者的必修课之一,而模板就是泛化编程的重要实现形式。
那么泛型编程具体是什么呢?我们通过一个实际需求来介绍这一机制,假设我们自定义了一些简单的类A、B、C,针对这些类,我们需要自己定义一个函数,该函数的输入参数是一个任意的类,运行时会输出一些基本的信息。
class A
{
public:
int _mem;
};
class B
{
public:
int _mem;
};
class C
{
public:
int _mem;
};
那么根据我们的所学,在不使用泛型编程的情况下,要如何实现这一需求呢?
由于不了解泛型编程,所以我们只能采用最朴实无华的方法,分别为所有的类定义我们需要的函数:
void MyFun(A data)
{
std::cout << "MyFun Called" <<std::endl;
}
void MyFun(B data)
{
std::cout << "MyFun Called" <<std::endl;
}
void MyFun(C data)
{
std::cout << "MyFun Called" <<std::endl;
}
通过这种方法,可以实现上述的需求,但是如果我们自定义了五个、十个甚至更多类呢?这显然不是一个聪明的做法,尤其考虑到我们每新声明一个类,就要多增添一个函数,这无疑很大程度上降低了我们的开发效率。
那么使用函数模板,要如何实现需求呢?
template<class T>
void MyFun(T data)
{
std::cout<< "MyFun Called" <<std::endl;
}
使用上述代码,就相当于对所有类都定义了一个MyFun 函数,在调用时,会输出"MyFun Called"的提示信息。
注意事项
在使用函数模板时,有一些事项需要注意:
- 函数模板的定义和声明需要放在一起,如果分开编写,就需要在源文件的末尾对所有可能使用的类进行特化声明
- 如果函数模板之间存在调用关系,注意要把被调用的函数放在调用者之前定义。
特化函数
通过上述的需求,我们初步地了解到了函数模板的功能,那么你或许会发现,通过第一个朴实的方法,尽管我们需要一些复杂的声明定义,但却可以为每个类定义不同的操作;可是如果使用函数模板,我们似乎只能对每个类进行相同操作了。提到这里,我们就又要引出本文的第二个知识点,特化函数。
使用函数模板,我们可以对每个类实现一个泛化的接口,但如果我们需要进行一些特化的操作,就不能使用最简单的函数模板了,需要使用特化函数对特定类的使用方法进行特化处理。
template<class T>
void inline MyFun(T data)
{
std::cout<< "MyFun Called" <<std::endl;
}
template<>
void inline MyFun(B data)
{
std::cout<< "MyFun Called By Class B." <<std::endl;
}
我们可以看到的是,前半部分代码我们仍然使用函数模板定义了一个泛化的MyFun 函数,但在后半部分代码中,我们特别针对B这个自定义类,进行了MyFun函数的特化。再此代码的基础上,使用MyFun方法处理其他类的对象时,会输出"MyFun Called",而如果处理B类的对象,会输出"MyFun Called By Class B."。因为我们此时已经实现了函数对于B类的特化。
需要注意的时,在MyFun声明之前,我添加了inline函数,避免编译时针对特化函数出现重复定义的情况。
到此,本文针对函数模板和特化函数的介绍就到这里了,希望这些简单的介绍和示例能够帮到渴望了解编程知识的你。同时也希望针对本文没有涉及到或是讲述不准确的地方,大家可以多多讨论,共同提高。