初识C++——模板

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档大家好,我是旗帜僵尸,刚刚没吃到,现在我将饿着带大家学习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,(int1.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++大家都会逐渐爱上它的懒狗写法,用的越来越爽。
饿死了,去吃了
下次见

你可能感兴趣的:(C++,c++,算法,数据结构)