简述C++泛型化编程思想
https://blog.csdn.net/Mary19920410/article/details/61914091
1、泛型的基本思想
泛型编程(Generic Programming)是一种语言机制,通过它可以实现一个标准的容器库。像类一样,泛型也是一种抽象数据类型,但是泛型不属于面向对象,它是面向对象的补充和发展。泛型编程在C++上的应用主要体现在两方面:函数模板和类模板,接下来我们通过两个例子说明。
1)函数模板
泛型,也就是我们说的任何类型,即不依赖于任何具体的类型。通常我们的操作都是依赖于具体的数据类型的,比如:
-
int add(int a, int b)
-
{
-
return a + b;
-
}
这个add函数依赖于int类型。你只能以int类型调用(即使是float,也会被转换为int型)。得到的结果也只能是int。那如果我们还需要一个float类型的add算法,就需要再写一个重载程序:
-
float add(float a, float b)
-
{
-
return a + b;
-
}
虽然在C++中可以通过函数重载来解决这个问题,但是反复写相同算法的函数是比较辛苦的,更重要的是函数重载是静态编译,运行时占用过多内存。
而泛型依赖于模板技术,可以支持任意数据类型,比如:
template <class T>
-
T add( T a, T b)
-
{
-
return a + b;
-
}
这个函数就可以用int,float等类型进行实例化,然后进行调用,这就不依赖任何具体的数据类型。例如:
-
int result = add<int>(1,2);
-
string result = add<string>("hello","world");
2)类模板
比如对栈的描述:
class stack{
push(参数类型); //入栈
pop(参数类型); //出栈
}
如果把上面的伪代码看作算法描述,没问题,因为算法与参数类型无关。但是如果把它写成可编译的源代码,就必须指明类型,否则是无法通过编译的。使用重载来解决这个问题,即对N种不同的参数类型写N个push和pop算法,这样是很麻烦的。
若对上面的描述进行改造如下:
首先指定一种通用类型T,不具体指明是哪一种数据类型:
class stack<参数模板T>
{
push(T); //入栈算法
pop(T); //出栈算法
}
这里的参数模板T相当于一个占位符,当我们实例化stack时,T会被具体的数据类型替换掉。
若定义对象S为stack类型,在实例化S时若我们将T指定int型,则:
-
class S
-
{
-
push(int); //入栈
-
pop(int); //出栈
-
}
这时,我们可以称class stack<参数模板T>是类的类,通过它可以生成具体参数类型不同的类。
综上,可以看出泛型在C++中的应用主要是模板函数和模板类。
2、定义模板函数
函数模板是一个独立于类型的函数,可以产生函数的特定类型版本。
模板定义以关键字template开始,后接尖括号括住的模板形参表。
模板形参可以是表示类型的类型形参(type parameter),也可以是表示常量表达式的非类型形参(nontype parameter)。如下面的程序中的T是类型形参。
-
/*
-
implement strcmp-like generic compare function
-
*/
-
#include <iostream>
-
#include <string>
-
using namespace std;
-
template <typename T> //类型形参,若多个类型形参,则<typename T1, typename T2>
-
int compare(const T &v1, const T &v2)
-
{
-
if(v1 < v2) return -1;
-
if(v2 < v1) return 1;
-
return 0;
-
}
-
int main()
-
{
-
cout << compare(1,2) << endl;
-
string s1 = "hello", s2 = "world";
-
cout << compare(s1, s2) << endl;
-
return 0;
-
}
使用函数模板时,编译器会将模板实参绑定到模板形参。编译器将确定用什么类型代替每个类型形参,用什么值代替每个非类型形参,然后产生并编译(称为实例化)该版本的函数。
上面的例子中,编译器用int代替T创建第一个版本,用string代替T创建第二个版本。
3、定义模板类
在定义的类模板中,使用模板形参作为类型或值的占位符,在使用类时再提供具体的类型或值。例如:
-
template <typename T>
-
class Queue
-
{
-
public:
-
Queue();
-
T &front();
-
const T & front() const;
-
void push(const T&);
-
void pop();
-
bool empty()const;
-
private:
-
//...
-
};
与调用函数模板不同,实用类模板时,必须为模板形参指明指定数据类型,例如:
-
Queue<int> qi; // Queue that holds ints
-
Queue<string> qs; // Queue that holds strings