Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/148.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用于使用虚拟接口对象的范围(c+;+;11)_C++_C++11 - Fatal编程技术网

C++ 用于使用虚拟接口对象的范围(c+;+;11)

C++ 用于使用虚拟接口对象的范围(c+;+;11),c++,c++11,C++,C++11,我正在编程接口,我想以一种通用的方式对其内容进行交互。所以,一般来说,我的界面有这样的原型: class Interface { public: class Iterator; virtual Interface::Iterator* begin() = 0; virtual Interface::Iterator* end() = 0; class Iterator { public: virtual const Iterator* operator++(

我正在编程接口,我想以一种通用的方式对其内容进行交互。所以,一般来说,我的界面有这样的原型:

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;
  };
};
下面是一个简单专业化的例子:

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;
  };
};
派生类:公共接口
{
公众:
派生():数组{2,0,1,5,4,3}{};
迭代器*begin(){返回新的派生::ITERDRIVED(0);};
迭代器*end(){返回新的派生::iterderive(6);};
int数组[6];
公众:
类ITerDrived:公共接口::迭代器
{
公众:
它驱动(inti){pos=i;};
ITERDRIVED(ITERDRIVED&&i){pos=i.pos;};
常量接口::迭代器*运算符++()重写{++pos;返回此;};
bool操作符!=(const接口::迭代器&i){return pos!=dynamic_cast(i).pos;};
int position(){return pos;};
私人:
int pos;
};
};
到目前为止,一切顺利。现在,我想编写一段代码,允许我使用新的for范围对其内容进行迭代,如新标准(c++11)中指定的那样。注意,在RealInterface中,我将提供getter方法,因此,不需要使用dynamic_cast。i、 e:

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;
}
intmain()
{
接口*a=新派生的();
用于(自动i:a)
std::cout数组[dynamic_cast(i.get())->position()]end())\
*国际热核实验堆!=*(国际热核实验堆结束);++(*国际热核实验堆))
在for范围的位置。是否有机会使用新的for语句范围,或者我必须使用这种宏?

当您说:

Interface *a = new Derived();
for(auto i : a) 
a
是指针,在指针上迭代没有任何意义。您可能需要:

for (auto i : *a)
也就是说,迭代
a
指向的对象

这可能仍然不起作用,因为您的
Interface::begin
Interface::end
方法返回的是
Interface::Iterator*
,而不是
Interface::Iterator
,这是毫无意义的

您似乎希望能够使用
Interface::Iterator
的子类在派生类上进行迭代,但这行不通,因为
auto
需要能够为它构建的
i
对象(以及关联的迭代器)找出一个静态类型

如果要执行类似操作,则需要使迭代器对象封装指向类的指针,该类可以由派生类进行子类化,同时保持迭代器类本身的固定状态。类似于:

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; }
        :
然后从中导出

class Derived : Interface {
  class IteratorImpl : public Interface::IteratorImpl {
       :
  };
public:
  Iterator begin() { return Iterator(new IteratorImpl( ...
当然,您需要确保添加所有必需的析构函数、赋值运算符、解引用运算符等

这可能还需要对应该包含在您实际迭代的任何类型中的类型进行模板化

::迭代器是一个抽象对象,它必须是。因此,我无法返回具体对象

然后,您现在处于虚拟(运行时)多态性和泛型(编译时)多态性之间的冲突中。基于范围的for以及几乎所有现有的算法都使用具体对象作为迭代器。它们将被算法随意复制

为了实现这一点,您需要让您的迭代器将虚拟机器隐藏在自己的内部。这可以很简单,比如有一个基本的
迭代器
类,该类存储指向“真实”迭代器类的指针,它将所有调用转发给该类

您可以这样做:

class IteratorBase
{
public:
  virtual const IteratorBase* operator++() = 0;
  virtual bool operator!=(const IteratorBase& i) = 0;
};

class Iterator
{
public:
  explicit Iterator(IteratorBase *it) : m_it(it) {}
  const Iterator &operator++() {return Iterator(++(*m_it));}
  bool operator !=(const Iterator &i) {return *m_it != *i.m_it;}

private:
  IteratorBase *m_it;
};
您可以从
IteratorBase
派生迭代器

一般来说,泛型编程风格的接口往往避免使用指针。如果不是实际对象,它们更适合于引用。因此,如果您希望您的类能够很好地使用泛型编程,则必须遵循allow的约定。而且,一般来说,想要尝试执行类似于运行时pol的操作是非常奇怪的形态范围


指针不是范围;只有对具体类型的引用才可以是范围。因此,除非您专门化
std::begin
std::end
,否则您不能将指针传递到基于范围的
for
,但此代码不会编译。“您会遇到什么错误?您需要包装迭代器,因为您甚至无法创建副本。”(指迭代器),这对于许多泛型算法来说是必不可少的。例如,请看得更好:避免继承/多态性/虚拟函数,如果可能的话,使用模板和泛型编程。一旦Iterface::Iterator是一个抽象对象,我需要返回一个指针。所以,我不能返回一个具体的对象。@TomásBadan:Make
Iterator
's
operator*
返回一个指针,使指向的对象表现出多态性,其他任何东西都很奇怪。@honk,你能发布一个代码来演示你的确切意思吗?@TomásBadan:我只是建议你使用通常的迭代器语义,有关详细的实现,请参见上面的DyP链接。
class IteratorBase
{
public:
  virtual const IteratorBase* operator++() = 0;
  virtual bool operator!=(const IteratorBase& i) = 0;
};

class Iterator
{
public:
  explicit Iterator(IteratorBase *it) : m_it(it) {}
  const Iterator &operator++() {return Iterator(++(*m_it));}
  bool operator !=(const Iterator &i) {return *m_it != *i.m_it;}

private:
  IteratorBase *m_it;
};