const迭代器与模板构造函数

在自己实现C++中list的时候,当实现const迭代器的时候,发现报错了,一直思考到现在
才发现是一个,很简单的问题,但是也让我有了一点感受,我在这里给大家分享一下。

文章目录

  • 1.当时遇到的问题
  • 2.解决方法
  • 3. 自己的感悟

1.当时遇到的问题

这是list的构造函数部分
const迭代器与模板构造函数_第1张图片
这是list迭代器调用的部分。
const迭代器与模板构造函数_第2张图片
当我运行这样一段代码的时候,会出现这样的错误:
const迭代器与模板构造函数_第3张图片
看得更清楚一点:
const迭代器与模板构造函数_第4张图片
而这么写的时候是没问题的:

void Print(const zsw::list<int>& ls)
{
	zsw::list<int>::const_iterator cit = ls.begin();
	while (cit != ls.end())
	{
		cout << *cit << endl;
		cit++;
	}
}

int main()
{
	zsw::list<int> ls;
	ls.push_back(1);
	ls.push_back(2);
	ls.push_back(3);
	ls.push_back(4);

	Print(ls);
	//zsw::list::const_iterator cit = ls.begin();
	//while (cit != ls.end())
	//{
	//	cout << *cit << endl;
	//	cit++;
	//}
	return 0;
}

const迭代器与模板构造函数_第5张图片

我当时想不通,为什么会出现这样的问题。
我一直以为这个问题是出现在begin函数上,因为我当时想的是,我左边是const迭代器对象,begin函数有两个一个是普通版本,一个是const版本,我一直认为右边的begin函数的返回值是:
const迭代器与模板构造函数_第6张图片
这里就出现了第一个错误,不理解函数重载的功能,调用重载函数,区别应该是体现在调用对象和传的参数上来体现。这里的ls是普通对象,所以调用的应该是普通版本的begin函数。
既然是调用的普通begin函数返回的就是普通迭代器,这就是问题的所在,我begin函数返回的的对象类型是Iterator,而对象cit的类型是Iterator,两者是不同的类型,而在cit的模板类实例化之后,cit是没有关于Iterator类型的构造函数的:
const迭代器与模板构造函数_第7张图片

2.解决方法

它这里的构造函数只有用节点或者同类型的迭代器来初始化。
所以我们只需要添加这样的一个构造函数。
const迭代器与模板构造函数_第8张图片
可以看到它是一个模板函数,这样就可以通过Iterator类型来构造Iterator,而这其中T1和T应该具有相似特性,为了传参正确,更严谨的写法:
const迭代器与模板构造函数_第9张图片
上面的解决方法我是从STL中map的一个返回值理解的:
const迭代器与模板构造函数_第10张图片

我们看到map的插入函数的参数是这样的一个,我们来看看它是什么:
const迭代器与模板构造函数_第11张图片
其实它是一个结构体:

在这里插入图片描述
假如我们现在使用以下map:
const迭代器与模板构造函数_第12张图片
它的编译的没有错误的,这显然与我们上面遇到的问题一样,map的插入函数需要的对象是pair,而对应到这里那它所需要的参数类型是pair,我们传的类型是pair这又是两个不一样的类型。那么很显然解决方法就也是从这里来的:
const迭代器与模板构造函数_第13张图片
在pair里就有这么一个模板构造函数。
可以看出这种构造函数又能充当拷贝构造又能充当构造

3. 自己的感悟

我们在上面看到一个pair传参给pair的引用,好像跟这里有点相似:
const迭代器与模板构造函数_第14张图片
可以看到它可以编译通过。那看这个,这不就是单个内置类型的成员变量的自定义类型之间的隐式类型转换嘛,要知道内置类型在C++中也是有“构造函数”的。
再看一段代码:

template<class T1, class T2>
class A
{
public:
	A()
	{}

	template<class N1, class N2>
	A(const A<N1, N2>& a)
		:_a(a._a)
		, _b(a._b)
	{}

	T1 _a;
	T2 _b;
};

void func(const A<double, double>& a)
{
	cout << "void func(A a)" << endl;
}

int main()
{
	A<int, int> a1;
	func(a1);

	return 0;
}

const迭代器与模板构造函数_第15张图片
也是能编译通过的。
const迭代器与模板构造函数_第16张图片
那这里能够实现的原因还是因为,有着隐式类型转化的作用。而隐式类型转化又有着更底层的内置类型转换(比如double转int)的构造逻辑,或者是自定义类型本身就有相关类型的构造函数(例如const char*转string)这种转化是基于两种类型具有相似的特性,所以隐式类型转换和不同类型间的构造函数是相辅相成的。
这就是基于list的const迭代器得出的一点感悟,要是错了的话,希望能够改正我。

你可能感兴趣的:(算法,c++)