#include <iostream>
using namespace std;
template <typename T> class Iterator
{
T * ptr;
public:
Iterator(T * addr)
{
ptr=NULL;
ptr=addr;
}
//not working
//virtual Iterator * operator ++(int x);
/*Iterator * operator ++(int x)
{
(this->ptr)++;
return this;
}*/
T operator *()
{
return *ptr;
}
};
template<typename T>
class Vector{
T * a;
public:
Vector(size_t n)
{
a=new T[5];
}
T& operator [](int x)
{
return a[x];
}
class iterator: public Iterator<T>
{
public:
iterator(T * addr): Iterator<T>(addr)
{}
/* not working
Iterator<T> * operator ++(int x)
{
Iterator<T>::ptr++;
return this;
}*/
//working now
iterator * operator ++(int x)
{
Iterator<T>::ptr++;
return this;
}
};
iterator begin()
{
iterator ob(&a[0]);
return ob;
}
};
int main()
{
Vector <char> v(5);
for(int i=0;i<5;i++)
v[i]=i+65;
for(int i=0;i<5;i++)
cout<<v[i]<<endl;
/*~~~~~~ What I want~~~~~~
Iterator <char> p=v.begin();
*/
// what is working now:
Vector<char>:: iterator p=v.begin();
while(*p){
cout<<*p<<endl;
p++;
}
return 0;
}
在上面的代码中,我想在Iterator类中创建operator ++(),虚拟,以便在main中我可以使用:
Iterator <char> ptr=v.begin();
而不是必须使用:
Vector <char>:: iterator p=v.begin();
这是一个带有运行时多态性的基类引用,用于确定调用哪个++运算符,具体取决于值是向量还是列表。但是,当我在Iterator类中将其声明为虚拟时,它无效。我必须专门为内部类声明它,但我想要一个像Java一样的单一接口。我试图在c ++中实现java集合层次结构以获得更好的结构。出了什么问题? 是不是因为Iterator是一个模板类,它使得返回类型Iterator也是模板,也就是说,operator ++()函数是一个模板函数?我知道模板函数不能是虚拟的,只有具体的函数才能是虚拟的。可以做些什么来解决这个问题?
答案 0 :(得分:0)
只能通过指针调用虚函数。您的begin
函数不返回指针。如果你修复了那么你会得到很多与类型转换相关的编译错误。
您也可以使用引用,但它应该是r值引用:
Iterator<char> &&p = v.begin();
答案 1 :(得分:0)
以下是具有正确后缀增量版本的示例实现:
template<typename T>
class Iterator
{
private:
T* ptr;
public:
Iterator(T* ptr1):ptr(ptr1)
{
}
virtual Iterator operator ++(int)
{
Iterator result(*this);
(this->ptr)++;
return result;
}
T operator*()
{
return *ptr;
}
};
template<typename T>
class Vector
{
private:
T* data;
public:
Vector()
{
data = new T(100);
for(int i=0;i<100;i++)
data[i]=i;
}
Iterator<T> begin()
{
return Iterator<T>(&(data[0]));
}
};
答案 2 :(得分:0)
让我先说一下,你的实施不会像你想象的那样有效。目前看不到所有其他答案。
使用指针作为多态迭代器的实现注定要失败,但是,multiorhphsm并没有改变你必须实现所有具有多态性的具体迭代器这一事实。
与Java类似(我会假设有些熟悉),通过接口可以实现全局多态Iterator
。现在C ++没有专用接口,而是我们所拥有的纯虚拟类。
template<typename T>
class Iterator
{
public:
virtual Iterator& operator++() = 0; // pure virtual
// other methods
};
template<typename T>
class Vector
{
class Iterator // Vector's concrete Iterator
: public ::Iterator<T> // analogous to implements in Java
{
public:
Iterator& operator++() override { /* implementation */ }
// other methods...
};
};
template<typename T>
class List
{
class Iterator // List's concrete Iterator
: public ::Iterator<T> // implements
{
public:
Iterator& operator++() override { /* implementation */ }
// other methods...
};
};
由于多态性仅适用于引用和指针,因此需要明确编写C ++中的引用
Vector<int> v;
List<int> l;
Iterator<int>&& rit = v.begin();
const Iterator<int>& crit = l.begin();
是你如何使用Iterator
。
作为最后一点,多态性是一种工具,滥用它比没有它更糟糕。请考虑性能损失并权衡其提供的灵活性。
答案 3 :(得分:-1)
您的代码几乎可以正常运行。我只需修复3个问题:
ptr
,那么Iterator
应该在virtual Iterator<T> ...
类中保护而不是私有#include <iostream>
using namespace std;
template <typename T> class Iterator
{
protected:
T * ptr;
public:
Iterator(T * addr)
{
ptr=NULL;
ptr=addr;
}
//not working - in fact works perfectly
virtual Iterator<T> * operator ++(int x)
{
(this->ptr)++;
return this;
}
T operator *()
{
return *ptr;
}
};
template<typename T>
class Vector{
T * a;
public:
Vector(size_t n)
{
a=new T[5];
}
T& operator [](int x)
{
return a[x];
}
class iterator: public Iterator<T>
{
public:
iterator(T * addr): Iterator<T>(addr)
{}
/* not working
Iterator<T> * operator ++(int x)
{
Iterator<T>::ptr++;
return this;
}*/
//working now but useless as we can use the base class version
/*iterator * operator ++(int x)
{
Iterator<T>::ptr++;
return this;
}*/
};
iterator begin()
{
iterator ob(&a[0]);
return ob;
}
};
int main()
{
Vector <char> v(5);
for(int i=0;i<5;i++)
v[i]=i+65;
for(int i=0;i<5;i++)
cout<<v[i]<<endl;
v[5] = 0; // set a null at the end of the vector
/*~~~~~~ What I want~~~~~~ and that works...*/
Iterator <char> p=v.begin();
// what is working now:
//Vector<char>:: iterator p=v.begin();
while(*p){
cout<<*p<<endl;
p++;
}
return 0;
}
所以这个编译没有警告,并且与Clang 3.4.1一起正常运行:
operator ++
您可以在Vector类中取消注释{{1}}的覆盖版本,它也可以正常工作。