我正在编程接口,我想以一种通用的方式对其内容进行交互.所以,一般来说,我的接口都有这样的原型:
class Interface
{
public:
class Iterator;
virtual Interface::Iterator* begin() = 0;
virtual Interface::Iterator* end() = 0;
class Iterator
{
public:
virtual const Iterator* operator++() = 0;
virtual bool operator!=(const Iterator& i) = 0;
};
};
Run Code Online (Sandbox Code Playgroud)
和吼叫,是一个简单的专业化的例子:
class Derived : public Interface
{
public:
Derived() : array {2, 0, 1, 5, 4, 3} {};
Iterator* begin() { return new Derived::IterDerived(0);};
Iterator* end() { return new Derived::IterDerived(6);};
int array[6];
public:
class IterDerived : public Interface::Iterator
{
public:
IterDerived(int i) {pos = i;};
IterDerived(IterDerived&& i) {pos = i.pos;};
const Interface::Iterator* operator++() override { ++pos; return this;};
bool operator!=(const Interface::Iterator& i) { return pos != dynamic_cast<const Derived::IterDerived&>(i).pos;};
int position() { return pos;};
private:
int pos;
};
};
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.现在,我想编写一段代码,允许我使用new for range来迭代其内容,如新标准(c ++ 11)中所指定的那样.请注意,在实际界面中,我将提供getter方法,因此使用dynamic_cast是不必要的.即:
int main()
{
Interface *a = new Derived();
for(auto i : a)
std::cout << dynamic_cast<Derived*>(a)->array[dynamic_cast<Derived::IterDerived*>(i.get())->position()] << " ";
std::cout << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码没有编译.为了编译,我需要以下列形式使用宏:
#define FOR_ITERATOR(iter, object) \
for(std::unique_ptr<Interface::Iterator> iter((object)->begin()), \
iter##end((object)->end()); \
*iter != *(iter##end); ++(*iter))
Run Code Online (Sandbox Code Playgroud)
在范围的地方.有没有机会使用新的语句范围,还是我必须使用这种宏?
当你说:
Interface *a = new Derived();
for(auto i : a)
Run Code Online (Sandbox Code Playgroud)
a是指针,迭代指针实际上没有任何意义.你可能想要:
for (auto i : *a)
Run Code Online (Sandbox Code Playgroud)
也就是说,迭代a指向的对象.
这可能仍然无效,因为你Interface::begin和Interface::end方法返回的是一个Interface::Iterator *而不是一个Interface::Iterator,这是无稽之谈.
您似乎希望能够使用子类Interface::Iterator来迭代派生类,但这不起作用,因为auto需要能够为i它构建的对象(及其关联的迭代器)找出静态类型.
如果你想做这样的事情,你需要让你的迭代器对象封装一个指针,该指针可以被Derived子类化,同时保持迭代器类本身的固定.就像是:
class Interface
{
public:
class Iterator;
virtual Interface::Iterator begin() = 0;
virtual Interface::Iterator end() = 0;
protected:
class IteratorImpl {
public:
virtual IteratorImpl &operator++() = 0;
virtual bool operator!=(const Iterator& i) = 0;
virtual IteratorImpl *clone() = 0;
};
};
public:
class Iterator {
protected:
class IteratorImpl *impl;
public:
Iterator(IteratorImpl *a) : impl(a) {}
Iterator(iterator &a) : impl(a.impl->clone()) {}
Iterator &operator++() { ++*rep; return this; }
:
Run Code Online (Sandbox Code Playgroud)
然后你从中得到这个
class Derived : Interface {
class IteratorImpl : public Interface::IteratorImpl {
:
};
public:
Iterator begin() { return Iterator(new IteratorImpl( ...
Run Code Online (Sandbox Code Playgroud)
当然,您需要确保添加所有必需的析构函数,赋值运算符,解引用运算符等.
这可能还需要模仿应该包含在您实际迭代的任何类型中的类型.