可能会将 c++ 中模板和 java 或 c# 中的泛型来作比较,不过 c++ 中模板是具有无限力量,功能远远超出 java 和 c# 中的泛型。要是想深入了解模板,需要下一番功夫。有的开发人员可以写出强大且复杂的模板。
那么什么是模板,有点类似我们了解元编程,就是让代码生成代码。c++ 编译器会根据定义好的模板规则在编译期间为您生成代码。这就是模板的定义也是模板的作用。
#include <iostream>
void Print(int val)
{
std::cout << val << std::endl;
}
int main(int argc, char const *argv[])
{
Print(5);
std::cin.get();
}
这里简单写了输出的函数,接收int
作为参数进行输出。
int main(int argc, char const *argv[])
{
Print(5);
Print("hello");
std::cin.get();
}
如果想要我们的Print
也支持对字符串输出,我们就需要重载一下这个函数void Print(std::string val)
。
void Print(std::string val)
{
std::cout << val << std::endl;
}
通过重载多次```Print()````,可以让函数接收更多类型参数进行输出。这样做当然没有问题,很多人也喜欢这样做。现在我们通过模板来重构我们代码让他看起来更简单易懂些。
template <typename T>
void Print(T val)
{
std::cout << val << std::endl;
}
int main(int argc, char const *argv[])
{
Print(5);
Print("hello");
Print(5.0f);
std::cin.get();
}
使用模板定义一个类型 T 作为泛型,其实 T 是类型变量,根据我们传入类型而定。这样代码看起来清晰易懂。
- template 这个关键字告诉编译器这是个模板需要在编译期间进行处理
- 模板参数是
typename T
告诉编译器这是 typename 而 T 是其名称可以为任意名称,这里是一种习惯,习惯将其命名为 T。 - 这里编译器根据传值进行类型推断对 T 进行赋值,我们也可以显式地对 T 进行赋值。
Print<int>(5);
其实模板背后工作是根据我们传入类型实际创建出一个一个接收不同类型作为参数Print()
函数。
#include <iostream>
#include <string>
template <int N>
class Array
{
private:
int m_Array[N];
public:
int getSize() const { return N; }
};
int main(int argc, char const *argv[])
{
Array<5> array;
std::cout << array.getSize() << std::endl;
std::cin.get();
}
在这个例子中给出模板更多的功能,通过模板我们实现一个可以在编译期间指定大小数组类。在编译期间会根据模板的 N 的值生成对应代码。
class Array
{
private:
int m_Array[5];
public:
int getSize() const { return 5; }
};
我们可以追加指定 T 表示类型,来让 Array 变得更加灵活。
template <typename T, int N>
class Array
{
private:
T m_Array[N];
public:
int getSize() const { return N; }
};
Array<int, 5> array;
当然模板不仅这些,我们可以写出复杂到难以理解模板,不过个人推荐不要痴狂于模板,将模板用到恰到好处即可。过渡使用可能适得其反。
网友评论