C++ 重写的方法不适用于基于范围的循环的范围\表达式

C++ 重写的方法不适用于基于范围的循环的范围\表达式,c++,C++,对操作符*的第一个调用(实时示例第38行)正在执行预期的操作,它调用被重写的方法operator\u deref()。而第二个(实时示例第40行)调用的是父方法。我错过了什么 #包括 类范围{ 受保护的: int _iter=0,最后; 虚拟整型运算符_deref()常量{ std::cout基于范围的for循环使用在类定义中不多态的begin/end成员函数 注: 评论中有一些不正确的断言: 如果将派生类的定义更改为: class RangeC : public RangeP{ p

操作符*
的第一个调用(实时示例第38行)正在执行预期的操作,它调用被重写的方法
operator\u deref()
。而第二个(实时示例第40行)调用的是父方法。我错过了什么

#包括
类范围{
受保护的:
int _iter=0,最后;
虚拟整型运算符_deref()常量{

std::cout基于范围的for循环使用在类定义中不多态的begin/end成员函数


注: 评论中有一些不正确的断言:

如果将派生类的定义更改为:

class RangeC : public RangeP{
    public:
    int operator_deref() const override{ // Enhanced operator
        std::cout << "Child Deref called" << std::endl;
        return 0;
    }

public:
    RangeC(int last_) : RangeP(last_) {};
    virtual const RangeC& begin() const { return *this; }
    virtual const RangeC& end()   const { return *this; }

};

原因可在以下网址找到:

如上所述:

{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
这里您看到的是
\u begin
是begin表达式的一个副本。因此您最终编写了
auto\u begin=\u range.begin();

如果它有类似于
auto&&
的功能,它可以支持引用。现在您遇到了我们称之为切片的情况。这是对抽象对象的复制,其中原始对象是派生类,副本是基类型

解决这个问题的一种方法是创建一个单独的迭代器类,该迭代器类充当代理

编辑

class RangeP {
 protected:
  int _last;
  virtual int operator_deref(int iter) const {
    std::cout << "Parent Deref called" << std::endl;
    return iter;
  }

 public:
  class const_iterator final {
   public:
    const_iterator(const RangeP &range, int iter) : _range{range}, _iter{iter} {}
    bool operator!=(const const_iterator &rhs) const { return _iter != rhs._iter; }
    void operator++() { ++_iter; }
    int operator*() { return _range.operator_deref(_iter); }
    const RangeP &_range;
    int _iter;
  };

  RangeP(int last_) : _last(last_) {}
  // Iterable functions
  auto begin() const { return const_iterator{*this, 0}; }
  auto end() const { return const_iterator{*this, _last}; }
};

class RangeC : public RangeP {
  int operator_deref(int iter) const override {  // Enhanced operator
    std::cout << "Child Deref called" << std::endl;
    return 0;
  }

 public:
  RangeC(int last_) : RangeP(last_){};
};
类范围p{
受保护的:
int_last;
虚整数运算符_deref(int iter)const{

std::cout这是真的,但是为了得到它调用operator*()的元素,operator_deref()@Bernd不,它没有!对,我编辑了我的评论…Ups,你是对的@M.A.非常感谢!你不需要在子类中使用
virtual
关键字。但是你确实需要在基类中使用它。这不能通过制作
begin()来实现吗
/
end()
virtual并在子类中实现它们?你不需要虚拟方法来实现它,只要有begin/end就可以编译它,因为你知道正确的类型。但是,一旦你在不知道基类是否派生的情况下循环这个基类,代理迭代器是唯一的方法。这正是关键所在!@JVApen、 你将如何编写这个代理?你能提供一个实例吗?谢谢你的回答!@有人我添加了这个。
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr; __begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
class RangeP {
 protected:
  int _last;
  virtual int operator_deref(int iter) const {
    std::cout << "Parent Deref called" << std::endl;
    return iter;
  }

 public:
  class const_iterator final {
   public:
    const_iterator(const RangeP &range, int iter) : _range{range}, _iter{iter} {}
    bool operator!=(const const_iterator &rhs) const { return _iter != rhs._iter; }
    void operator++() { ++_iter; }
    int operator*() { return _range.operator_deref(_iter); }
    const RangeP &_range;
    int _iter;
  };

  RangeP(int last_) : _last(last_) {}
  // Iterable functions
  auto begin() const { return const_iterator{*this, 0}; }
  auto end() const { return const_iterator{*this, _last}; }
};

class RangeC : public RangeP {
  int operator_deref(int iter) const override {  // Enhanced operator
    std::cout << "Child Deref called" << std::endl;
    return 0;
  }

 public:
  RangeC(int last_) : RangeP(last_){};
};