1

一些(相关的?)背景: 我有一个类在 c++ 中提供类似迭代器的功能。它用于解压缩大型数据集。在幕后,我有一个CompressedData目标。迭代器类迭代压缩数据并返回未压缩Data对象

Data ExpandingIterator::operator*() const;

解引用操作符返回一个 Data 而不是 Data& 因为在任何地方都没有存储可以保存未压缩的 Data 对象。例如,压缩数据可能包含以下三个条目:

  • 5'3',
  • 3个'1',
  • 6个'0'

然后,当您使用 ExpandingIterator 迭代此集合时,您将获得:

3, 3, 3, 3, 3, 1, 1, 1, 0, 0, 0, 0, 0, 0

3s、1s 和 0s 永远不会同时存在于数组中的某个位置。它们是从压缩数据中一次一个地扩展的。现在,真实数据比简单的整数更复杂。有数据、时间戳和其他方法可以将数据转换为其他形式的数据。

问题: 我已经成功实现了上面提到的解引用操作符。问题是当我使用 ExpandingIterator 并想要访问 Data 对象上的方法之一时,我最终会写

(*iterator).Method()

我宁愿写

iterator->Method();

到目前为止,这个问题的解决方案似乎很明显。我需要实现 -> 运算符。这最初看起来很简单,但我担心我遗漏了一些东西(可能很明显)

起初,我尝试过:

Data ExpandingIterator::operator->() const{
    return **this; //Just call the regular dereference operator
}

但这给我留下了错误消息:类型'Data'没有重载成员'operator ->'。进行更多研究,并基于此处的答案,我相信有一些可能的解决方案:

  1. 也给“数据”一个 -> 运算符。不幸的是,我认为这只会将我对问题的误解推到 Data 对象中,在那里我会遇到与我在这里遇到的完全相同的问题
  2. 返回指向“数据”对象的指针。不幸的是,Data 对象并不真正存在于可以指向的位置,所以这似乎是一个非首发
  3. 给 Data 一个隐式对象以进行指针转换 - 这对我来说似乎很荒谬。
  4. 放弃并回家。只需执行 (*Data).Method() 并被 c++ 击败。

有人可以帮助消除对 -> 运算符应该如何实现的误解(或缺乏理解)吗?

4

2 回答 2

2

要重载operator->(),您最终需要得到一个实际的指针,例如,aT const*代表合适的类型T。当您返回不同于 from 的指针时operator->(),编译器将调用operator->()返回的对象。

从它的声音来看,在您的情况下,返回一个在给定位置填充相应数据的Data对象可能是合理的。ExpandingIterator::operator->()当然,Data需要另一个operator->()可以返回的,例如指向自身的指针,即this假设它Data具有您要调用的实际成员函数。

原则上,在你最终到达一个你真正想要返回指针的对象之前,你可以有多个间接。但是,似乎一旦您返回了一个Data对象,您手中就有一个实体,您想要调用一个成员函数,因此,返回一个指向它的指针应该可以工作。请注意,临时对象的规则仍然适用,即,如果您返回一个Data对象,它将在完整表达式的末尾消失。

于 2013-09-16T21:56:07.097 回答
2

您可以在迭代器中定义一个助手类,该类可以将->操作委托给一个Data指针。

class ExpandingIterator {
    //...
    struct DataPtr {
        Data data;
        DataPtr () {}
        DataPtr (const Data &d) : data(d) {}
        Data * operator -> () { return &data; }
    }
    //...
    DataPtr operator -> () const { return **this; }
    //..
};
于 2013-09-16T22:01:59.893 回答