Essential c++初学 第三章 basic c++ programming

谁说我不能喝 提交于 2019-12-25 19:53:42

泛型编程

1.指针的算术运算
为了操作容器中的数据而不用管它的数据类型是什么,使用泛型(generic)算法,不直接在容器身上进行操作,而是借用一对iterator,标识我们要进行迭代的范围。
1.对于array来说,传入array而不管array里面是什么

//写出template泛型 find()函数
template <typename T>
T* find( T *first,  T *last, const T &value) {
	if (!first || !last)
		return 0;
	for (; first != last; ++first) {
		if (*first == value)
			return   first;//输出所查找元素的地址
	}
	return 0;
}

int main(){
	int ia[8] = { 1,2,3,4,5,6,7,8 };
	int *pi = find(ia,ia+8,ia[3]); //find()返回所查找元素的地址
}

2.传入vector而不管vector里面是什么

#include <vector>
#include <iostream>

//编写泛型find函数


template <typename T>
T* find( T *first,  T *last, const T &value) {
	if (!first || !last)
		return 0;
	for (; first != last; ++first) {
		if (*first == value)
			return  first;
	}
	return 0;
}

template <typename T>
inline T * begin(const std::vector<T> &vec) {
	return vec.std::empty() ? 0 : &vec[0];
}

template <typename T>
inline T * end(const std::vector<T>&vec) {
	return vec.std::empty() ? 0 : &vec[vec.std::size()];
}

int main() {
	int ia[8] = { 1,2,3,4,5,6,7,8 };
	std::vector<int> ib;
	ib.insert(ib.begin(), ia, ia + 9);
	std::cout << "ib is " << &ib << "\nib[7]is" << &ib[7]
		<<"\nia is "<<ia<<"\nia[7] is "<<&ia[7];//验证了vector和array确实都是连续内存
	int *pi = find(begin(ib),end(ib),ib[3]);//why:find报错
	//std::cout << find(begin(ib), end(ib), ib[3]) << "  ";
	getchar();
	
}

但是对于list等非连续空间内的指针,指针的算术运算就不适用了,因此需要在底层指针的行为之上提供一层抽象,取代程序原本的“指针直接操作”方式,我们把底层指针的处理放在这个抽象层当中,让用户无须直接面对指针操作。这样就可以只提供一个find()函数就可以操作std所提供的所有的容器类。

#include <vector>
#include <iostream>
#include <string>
#include <list>

std::vector<std::string> svec;
std::vector<std::string>::iterator iter = svec.begin();

namespace mine {
	template <typename T, typename IT>
	IT find(IT first, IT last, const T &value)
	{
		for (; first != last; ++first) {
			if (value == *first)//值运算,故first解包
				return first;
		}
		return last;
	}
}
/*发现如果用find(),会和标准库的find()重名,导致报错“有多个重载函数find实例与
参数列表匹配,函数调用不明确”     
问题原因:自定义的find定义位置是全局变量,因此污染了namespace
解决方法:1.函数改名 ,并以后不要定义与标准库重名的函数
2.给自定义变量加命名空间  如 namespace main{}*/
int main() {
	const int asize = 8;
	int ia[asize] = { 1,1,2,3,5,8,13,21 };//ia is an array
	
	std::vector<int> ivec(ia,ia+asize);//将ia[]赋值给vector
	std::list<int> ilist(ia, ia + asize);

	//find() return一个地址,故应该和pia存放的地址对比计算
	int*pia = mine::find(ia, ia + asize, 1024);
	if (pia != ia + asize)//pia is an int*
		std::cout << pia << std::endl;
	else
		std::cout << "none"<<std::endl;
	
	std::vector<int>::iterator it; //声明泛型迭代器it
	it = mine::find(ivec.begin(), ivec.end(), 21);
	if(it!=ivec.end())
		std::cout << *it << std::endl;
	else
		std::cout << "none";
	getchar();
	}

因此,定义函数时最好不要定义和标准库同名的函数名。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!