C++知识点58——类模板(3、类模板的成员模板)

接上一篇文章https://blog.csdn.net/Master_Cui/article/details/111824108

六、类模板中的成员模板

类的成员函数也可以被写成模板,因为模板的实例化需要在编译期确定,所以,成员模板不能是虚函数

仍然拿mystack举例

int main(int argc, char const *argv[])
{
	mystack<int, 10> si10;
	mystack<double, 20> sd20;
	si10=sd20;
	return 0;
}

根据前面的代码,当指定第五行时,会报错,因为operator=的两边的容器的类型不匹配

为了能实现不同类型容器的互相赋值和初始化,可以将拷贝构造函数和operator=写成模板的形式,变成成员函数模板

template <typename T, int maxcount, typename CONT = deque<T>>
class mystack
{
public:
	mystack();

	mystack(const mystack<T, maxcount, CONT> &rval);
	mystack<T, maxcount, CONT> &operator=(const mystack<T, maxcount, CONT> &rval);

	template <typename T2, int maxcount2, typename CONT2>
	mystack(const mystack<T2, maxcount2, CONT2> &rval);

	template <typename T2, int maxcount2, typename CONT2>
	mystack<T, maxcount, CONT> &operator=(const mystack<T2, maxcount2, CONT2> &rval);
	~mystack();
	void push(const T &ele);
	void pop();
	T top() const;
	bool empty() const {
		return elem.empty();
	}

private:
	CONT elem;
};

template <typename T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::mystack()
{
	cout<<__func__<<endl;
}

template <typename T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::mystack(const mystack<T, maxcount, CONT> &rval):elem(rval.elem)
{
	cout<<__func__<<endl;
}

template <class T, int maxcount, typename CONT>
mystack<T, maxcount, CONT> & mystack<T, maxcount, CONT>::operator=(const mystack<T, maxcount, CONT> &rval)
{
	cout<<__func__<<endl;
	if (this==&rval) {
		return *this;
	}
	this->elem=rval.elem;

	return *this;
}

template <class T, int maxcount, typename CONT>
template <typename T2, int maxcount2, typename CONT2>
mystack<T, maxcount, CONT>::mystack(const mystack<T2, maxcount2, CONT2> &rval)
{
	cout<<__func__<<endl;

	mystack<T2, maxcount2, CONT2> tmp=rval;
	elem.clear();
	while (!tmp.empty() && elem.size()<maxcount) {
		elem.push_front(tmp.top());
		tmp.pop();
	}
}

template <class T, int maxcount, typename CONT>
template <typename T2, int maxcount2, typename CONT2>
mystack<T, maxcount, CONT> & mystack<T, maxcount, CONT>::operator=(const mystack<T2, maxcount2, CONT2> &rval)
{
	cout<<__func__<<endl;
	if ((void*)(this)==(void*)(&rval)) {
		return *this;
	}

	mystack<T2, maxcount2, CONT2> tmp=rval;
	elem.clear();
	while (!tmp.empty() && elem.size()<maxcount) {
		elem.push_front(tmp.top());
		tmp.pop();
	}

	return *this;
}

template <typename T, int maxcount, typename CONT>
mystack<T, maxcount, CONT>::~mystack()
{
	cout<<__func__<<endl;
}

template <typename T, int maxcount, typename CONT> 
void mystack<T, maxcount, CONT>::push(const T &ele)
{
	if (elem.size()>=maxcount) {
		return;
	}
	//cout<<__func__<<endl;
	elem.push_back(ele);
}

template <typename T, int maxcount, typename CONT>
void mystack<T, maxcount, CONT>::pop()
{
	//cout<<__func__<<endl;
	try {
		elem.pop_back();
	}
	catch (out_of_range){
		cout<<"out_of_range"<<endl;
	}
}

template <typename T, int maxcount, typename CONT>
T mystack<T, maxcount, CONT>::top() const
{
	//cout<<__func__<<endl;
	try {
		return elem.back();
	}
	catch (out_of_range){
		cout<<"out_of_range"<<endl;
	}
}

上述代码中,拷贝构造函数和operator=实现了成员函数模板的版本,因为右值类型和左值的类型有可能不一致,所以需要指定新的模板参数,所以在声明模板参数时,需要分别写两次

template <class T, int maxcount, typename CONT>
template <typename T2, int maxcount2, typename CONT2>

这两个模板参数的顺序得按照先指定类模板参数,再指定成员函数模板参数的顺序,顺序不能颠倒

拷贝构造函数和operator=中调用了push_front,所以,要求传入的模板实参CONT和CONT2必须支持push_front

实现了拷贝构造函数和operator=的成员函数模板版本后,就可以跨类型(类型不能跨度太大,比如int to string)拷贝或者赋值了

int main(int argc, char const *argv[])
{
	mystack<int, 10> si10;
	for (int i=0;i<10;++i) {
		si10.push(i);
	}
	mystack<double, 20> sd20;
	for (int i=0;i<20;++i) {
		sd20.push(i);
	}
	si10=sd20;
    while(!si10.empty()) {
		cout<<si10.top()<<endl;
		si10.pop();
	}
	mystack<double, 10> sd10=si10;
	mystack<int, 10> si101=si10;
	return 0;
}

第17行代码执行的是拷贝构造函数的非成员函数模板的版本,所以,即使实现了拷贝构造函数和operator=的成员函数模板版本,拷贝构造函数和operator=的非成员函数模板版本也要保留

 

参考

《C++ Template》

《C++ Primer》

 

欢迎大家评论交流,作者水平有限,如有错误,欢迎指出

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值