1

我目前正在创建一组迭代器,它们的实现细节不同,但将用于相同的算法。因此,它们都必须具有相同的接口。为了实现这一点,我创建了一个抽象迭代器类,并在所有进一步的迭代器中从这个类继承。

这应该让您了解我的代码是什么样的:

class INodeIterator
{
public:
    virtual ~INodeIterator() {};
    virtual bool operator!= (const INodeIterator& other) =0;
    virtual bool operator== (const INodeIterator& other) =0;
    virtual INodeIterator& operator++ () =0;
    virtual INodeIterator& operator++ (int i) =0;
    virtual Node& operator* () =0;
};

class NodeIterator : public INodeIterator
{
public:
    /* snip */
    NodeIterator& operator++ (int i)
    {
        NodeIterator tmp(*this);
        ++(*this);
        return(tmp);
    }
};

现在我面临着与迭代器中的 C++ 后增量运算符重载相同的问题(使用 -Wall -Werror 编译):我的 operator++(int) 实现抛出一个警告(gcc 4.8.0)返回对临时的引用。链接问题中的解决方案是只返回对象而不是引用。

但是,这对我不起作用。如果我同时更改接口和派生类以返回对象而不是引用,则会出现以下错误(摘录、附加文件名等已删除):

INodeIterator.h:16:27: error: invalid abstract return type for member function ‘virtual INodeIterator INodeIterator::operator++(int)’
     virtual INodeIterator operator++ (int i) =0;
                           ^

NodeIterator.h:33:22: error: invalid covariant return type for ‘virtual NodeIterator NodeIterator::operator++(int)’
         NodeIterator operator++ (int i);
                      ^

INodeIterator.h:16:27: error:   overriding ‘virtual INodeIterator INodeIterator::operator++(int)’
     virtual INodeIterator operator++ (int i) =0;
                           ^

将派生类上的返回类型更改为 object 而不是抽象类上的预期返回“指定的返回类型冲突”错误。

我怎样才能使这项工作?

4

4 回答 4

3

尝试改变设计:让 NodeIterator 持有 INodeIterator 作为指针。NoteIterator 的所有方法都将委托给持有的 INodeIterator 对象。在这种情况下,您可以使用正确的签名:

struct IteratorInterface {
    virtual ~IteratorInterface() {}
    virtual std::unique_ptr<IteratorInterface> clone() const = 0;
    virtual void next() = 0;
};

class Iterator {
    std::unique_ptr<IteratorInterface> impl;
public:
    Iterator(std::unique_ptr<IteratorInterface> r) : impl(std::move(r)) {}
    Iterator(const Iterator &r) : impl(r.impl->clone()) {}
    Iterator& operator++() {
        impl->next();
        return *this;
    }
    Iterator operator++(int ) {
        Iterator tmp(*this);
        impl->next();
        return tmp;
    }
    void swap(Iterator &other) {
        other.impl.swap(impl);
    }
};

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    struct IteratorInterfaceImpl : IteratorInterface {
        int i;
        IteratorInterfaceImpl() : i(0) {}
        virtual std::unique_ptr<IteratorInterface> clone() const {
            return std::unique_ptr<IteratorInterface>(new IteratorInterfaceImpl(*this));
        }
        virtual void next() {
            i += 1;
        }
    };
    Iterator tmp(std::unique_ptr<IteratorInterface>(new IteratorInterfaceImpl()));
    tmp++;
    ++tmp;

    return 0;
}
于 2013-05-22T07:29:12.427 回答
1

void我能想到的唯一理智的方法是从INodeIterator::operator++(int)——即什么都没有回来。

您不能从后增量运算符返回引用,因为您必须创建一个返回引用的实际对象(存储先前的值)。该对象要么是动态分配的,并且必须被销毁(必须delete在返回的引用上显式调用),要么它是一个“局部变量”,operator++(int)并且在返回之前将被销毁:

virtual NodeIterator& operator++(int)
{
    NodeIterator prev_value(*this);
    ++(*this);
    return prev_value; // dangling/invalid reference, `prev_value` is destroyed
}

virtual NodeIterator& operator++(int)
{
    NodeIterator* pPrev_value = new NodeIterator(*this);
    ++(*this);
    return *pPrev_value; // have to explicitly call delete on the returned ref...
}

你也不能返回一个类型的对象,INodeIterator因为INodeIterator::operator++(int)它是一个抽象类。

于 2013-05-22T07:37:38.333 回答
0

您收到错误的原因

INodeIterator.h:16:27: error: invalid abstract return type for member function ‘virtual INodeIterator INodeIterator::operator++(int)’
     virtual INodeIterator operator++ (int i) =0;

是因为你的纯虚函数返回一个抽象类对象。

一种解决方案是使用 new 运算符并返回在堆中创建的对象,这是安全的。

 virtual INodeIterator& operator++ (int i) =0;

    NodeIterator& operator++ (int i)
    {
        NodeIterator* tmp = new NodeIterator (*this);
        ++(*this);
        return(*tmp);
    }
于 2013-05-22T07:22:41.933 回答
0

您的原型不正确。它应该是

NodeIterator operator++ (int i)

也就是说,删除引用返回,否则您将返回对超出范围的引用(您的tmp)不是一个好主意!

编译器在让您知道这一点方面非常有帮助!

我知道的不是你想听到的。

于 2013-05-22T07:25:22.137 回答