大家好,我是旗帜僵尸,刚刚没吃到,现在我将饿着带大家学习C++中的模板。
本篇文章将继续收录于我的C++专栏中,若想查看关于C++其它知识的文章也可以点击右方链接。C++
int ADD(int &a,int &b)
{
return a+b;
}
double ADD(double &a,double &b)
{
return a+b;
}
学习函数重载后,我们可以写出用于int与double的ADD函数。
但是,这样真的爽吗?真的符合我们的懒狗风格吗?
我们发现,两个ADD函数除了变量类型以外,其底层逻辑基本一致,由此引入我们的模板
//单参数
template<typename T>//或
T ADD(const T& a,const T& b)
{
return a + b;
}
//多参数
template<typename T1,typename T2>
T1 ADD(const T1& a,const T2& b)
{
return a + b;
}
T是虚拟类型,当在调用函数时,会自动推理得到正确的类型即隐式实例化。
例:ADD(1,2)
1.模板函数只有在调用时才会生成。对于ADD(1,2)和ADD(3.0,4.2)它们在调用时,会生成对应的函数,这些生成的函数会一直存在直到程序结束
2.typenames是定义模板参数的关键字,也可以用class
1.模板函数与非模板函数可以同时存在
int ADD(const int& a,const int& b)
{
return a + b;
}
template<typename T1,typename T2>
T1 ADD(const T1& a,const T2& b)
{
return a + b;
}
ADD(1,2);
而在执行ADD(1,2)时,编译器会用已经写好的。(懒狗)
2.对于单参的模板函数,其T类型的形参类型要相同
template<typename T>
T ADD(const T& a,const T& b)
{
return a + b;
}
ADD(1,1.4);//报错
形参类型不同时可以强制转换
ADD(1,(int)1.4);
ADD ( (double)1, 1.4) ;
也可以提前声明T的类型即显示实例化
ADD<int>(1,1.4);
ADD<double>(1,1.4);
template<typename T>
class 类模板名
{
//类的成员定义
}
//示范
template<typename T>
class Stack
{
public:
Stack(int capacity = 4)
{
_a = (T*)malloc(sizeof(T) * capacity);
if (_a == nullptr)
{
perror("malloc fail");
exit(-1);
}
_capacity = capacity;
_top = 0;
}
~Stack()
{
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
//传引用是减少拷贝,如果此时的x是自定义类型,那么x可能会很大
void Push(const T& x)
{
_a[_top++] = x;
}
private:
T* _a;
int _top;
int _capacity;
};
在使用时,类模板只能显式实例化:
Stack<int> st;
st.Push(1);
st.Push(2);
st.Push(3);
1.在 C++ 中,类模板的声明和定义必须放在一起,因为编译器在编译时需要检查类模板的具体实现。如果将声明和定义分离,编译器就无法检查类模板的具体实现,这将导致编译错误
2.类模板的成员函数本身是一个普通函数。不同的是,类模板的每个实例(如A, A等等)都有其自己版本的成员函数。因此,类模板的成员函数具有和模板相同的模板参数。换而言之,其成员函数都是模板函数。
今天学习了初阶模板的用法,相信随着不断深入学习C++大家都会逐渐爱上它的懒狗写法,用的越来越爽。
饿死了,去吃了
下次见