准备看个项目找实习,边看边学,一看到处都是template 和typename,好几年前学的C++都忘记光了,在这里先做个笔记复习一下。
template <class T>
T abs(T x) {
if(x < 0) return -x;
return x;
}
int main()
{
int x = 1;
cout << abs(x);
return 0;
}
上面是一个函数模板的例子,注意class改成typename在这种场景是一摸一样的。
函数模板VS模板函数
上面这玩意儿叫做函数模板,这两个容易搞混,就好像豆腐一碗和一碗豆腐,我们把重点放在后面
函数模板就是模板,模板函数就是函数。
函数模板本质上是函数重载的一种实现,在定义函数模板的时候是不是有自定义类型<class T> 或者<typename T>,当上面代码中abs(x)的时候,就会生成一个模板函数,将class T变成int类型,这个生成的重载函数就叫做模板函数。
从函数模板产生的模板函数都是同名的,C++在编译的时候会将重载函数取名字
例如
void foo(int x, int y);
C 编译之后在符号库中的名字为_foo,而C++编译器会产生像_foo_int_int之类的名字,这也是C++支持重载的原因(想了解更多可以搜一下extern C)。
那么在生成这个模板函数的过程中,万一有多个同名的重载函数,编译器会按照哪一个生成呢?
答案是:非模板函数>模板函数>类型转换。https://blog.csdn.net/Slience_Perseverance/article/details/20574423
类模板:
类模板的成员函数被认为是函数模板,因此当给出一个类模板的成员函数定义必须遵循函数模板的定义。
首先看类模板格式
template <typename T>
class Array
{
int size;
T *p;
public:
Array();
Array(int n);
T &operator[](int) const;
};
看上面黑体字,按照函数模板定义类成员函数
template <typename T>
Array<T>::Array()
{
size = 10;
p = new T[size];
}
template <typename T>
Array<T>::Array(int n)
{
size = n;
p = new T[size];
}
template <typename T>
T& Array<T>::operator[] (int i) const
{
if(i >= 0 && i < size)
return p[i];
}
这个就是对那个重载成员函数进行实现的代码。
在类模板之外定义成员函数就要按照上面这种方式。
类模板实例化
Array<int> m;
Array<int> m(5);
都是可以的,可以自行测试。
从属类型
上面的打了一遍之后就熟悉了,但是在看项目的过程中,我又发现了一种函数模板没见过的写法,
第二行开头怎么有个typename?我记得书上是没有的呀
去掉试试?
error: need ‘typename’ before ‘CTP::MakeUniqueResult<T>::scalar’
because ‘CTP::MakeUniqueResult<T>’ is a dependent scope
MakeUniqueResult<T>::scalar make_unique(
报错了,说这是dependent scope,必须要有这个typename,
https://blog.csdn.net/ljlinjiu/article/details/89384836?ops_request_misc=&request_id=&biz_id=102&utm_term=%E4%BB%8E%E5%B1%9E%E7%B1%BB%E5%9E%8B(dependent%20type),&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-3-89384836.142^v73^insert_down3,201^v4^add_ask,239^v2^insert_chatgpt&spm=1018.2226.3001.4187
上面这篇文章写的很详细。
大概意思就是如果不指明,编译器可能会不把它当成一个类型,而把他当成一个静态成员变量。