首页 > 解决方案 > 迭代的“基于范围”调用是什么

问题描述

我最近想知道远程工作是如何工作的,最后得到了如下图:

for(obj& temp_ref:range r)//hide iterator somewhere as the range defined.

对于每次迭代,只有当前对象的更新以在一个循环中完成工作,这对我来说是体面的解释。
   
 
但是当我尝试将范围和迭代器组合到一个混合类中时,
它应该在我的代码中调用哪个运算符++,
从某种意义上说,它应该是在基于范围的情况下调用派生类方法,
因为我将对象创建为派生对象,我的声明是虚拟的。

此处提供了代码,第一部分很好,但第二部分对我来说很奇怪。

#include <iostream>

namespace first
{
        template<class iterator>
        class range
        {
            public:
                range(iterator ina,iterator inb):a(ina),b(inb){};
                iterator a,b;
                iterator& begin(){return a;};
                iterator& end(){return b;};
        };
        template<class T>
        class iterator
        {
            public:
                iterator(T* ini):i(ini){};
                T* i;
                virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
                virtual T& operator* (){return *i;};
                virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
                virtual void operator++ (){i++;};
        };
        class jump2:public iterator<int>
        {
            public:
                jump2(int* ini):iterator<int>(ini){};
                virtual void operator++ (){i+=2;};
        };

}

namespace second
{
    template<class T>
    class iterator
    {

        public:
            iterator(T* inStart,T* inFinal):current(inStart),final(inFinal){};
            T* current;
            T* final;
            iterator<T> begin(){return iterator<T>(this->current,this->final);};
            iterator<T> end(){return iterator<T>(this->final,this->final);};
            virtual iterator<T>& operator= (const iterator<T>& other){this->current=other.current;this->final=other.final;return *this;};
            virtual T& operator* (){return *this->current;};
            virtual bool operator!= (iterator<T>& other){return this->current!=other.final;};



            virtual void operator++ ()
            {
                std::cout<<"<call base>";
                this->current=this->current+1;
            };



    };
    template<class T>
    class jumper:public iterator<T>
    {
        public:

            jumper(T* inStart,T* inFinal):iterator<T>(inStart,inFinal){};



            void operator++ ()
            {
                std::cout<<"<call deri>";
                this->current=this->current+2;
            };



    };
};

int main()
{

    int a[6]={1,0,2,0,3,0};

    //success
    {
        using namespace first;

        range<jump2> a_range(jump2(a),jump2(a+6));


        for(int store:a_range)
            std::cout<<store<<std::endl;
    }//pause();


    //Fail
    {
        using namespace second;

        jumper<int> a_iterator_call_jumper(a,a+6);

        for(int& i:a_iterator_call_jumper)
            std::cout<<i<<std::endl;

    }//pause();



    return 0;
};

这个输出是

1
2
3
1
<call base>0
<call base>2
<call base>0
<call base>3
<call base>0
<call base>

但它应该像

1
2
3
1
<call deri>2
<call deri>3
<call deri>

这件事出错是因为我用错了吗?
还是有一个我还没有找到的错误?

标签: c++inheritanceoperator-overloadingranged-loops

解决方案


    template<class iterator>
    class range
    {
        public:
            range(iterator ina,iterator inb):a(ina),b(inb){};
            iterator a,b;
            iterator& begin(){return a;};
            iterator& end(){return b;};
    };

    template<class iterator>
    class range
    {
        public:
            range(iterator ina,iterator inb):a(ina),b(inb){};
            iterator a,b;
            iterator begin() const {return a;};
            iterator end() const {return b;};
    };

是的。

    template<class T>
    class iterator
    {
        public:
            iterator(T* ini):i(ini){};
            T* i;
            virtual iterator<T>& operator= (const iterator<T>& other){this->i=other.i;return *this;};
            virtual T& operator* (){return *i;};
            virtual T operator!= (const iterator<T>& other){return this->i==other.i?0:1;};
            virtual void operator++ (){i++;};
    };

    template<class T>
    class iterator
    {
        public:
            iterator(T* ini):i(ini){};
            T* i;
            iterator( iterator const& ) = default;
            iterator& operator= (const iterator<T>& other) & = default;
            T& operator*() {return *i;};
            bool operator!= (const iterator& other) const {return this->i==other.i?0:1;};
            void operator++() {++i;};
    };

是的。

不要对迭代器使用标准的基于 C++ vtable 的多态对象模型;它们应该是正则类型,而基于 vtable 的多态对象模型是不正则的。

至于second,这不是一个好计划。迭代器和迭代的范围不是一回事。将它们粉碎在一起会使您的课程语无伦次。

C++ 迭代不是为动态调度(多态性)而设计的。你可以这样做,但它会影响性能,而且编写起来也不是一件容易的事。您基本上需要将虚拟分派隐藏在常规类型后面(您可以使用 vtables 进行分派,也可以使用 C++ 的基于 void 指针的类型擦除进行分派)。

如果您习惯于其他语言,许多其他源自 C++ 的语言都使用强制引用语义和垃圾收集来处理类类型的对象。他们的虚拟继承对象模型适用于引用变量,就像在 C++ 中的引用和指针类型一样。

C++ 相对古怪(在当今时代),因为它支持将复杂对象作为值类型,并且语言和标准库假定您大部分时间都在使用值类型。(请注意,指针是一种值类型;但它的值是指针,而不是对象),并且当您想要使用引用/指针语义时,您必须调整您的代码。


推荐阅读