簡體   English   中英

operator ++(int)重載與抽象基類和Wall

[英]operator++(int) overload with abstract base class and Wall

我目前正在創建一組迭代器,它們的實現細節會有所不同,但會在相同的算法中使用。 因此,它們必須具有相同的接口。 為此,我創建了一個抽象迭代器類,並在所有其他迭代器中繼承此類。

這應該可以讓您了解我的代碼是什么樣的:

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;
                           ^

將派生類的返回類型更改為對象但不在抽象類上更改會返回“指定的沖突返回類型”錯誤。

我怎樣才能做到這一點?

嘗試更改設計:讓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;
}

我能想到的唯一理智的方法是從INodeIterator::operator++(int)返回void - 即沒有。

您不能從后增量運算符返回引用,因為您必須創建一個實際對象(存儲前一個值),並返回一個引用。 這個對象要么是動態分配的,要么必須被銷毀(必須在返回的引用上顯式調用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::operator++(int)返回INodeIterator類型的對象,因為它是一個抽象類。

你得到錯誤的原因

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);
    }

你的原型是不正確的。 它應該是

NodeIterator operator++ (int i)

也就是說,刪除引用返回,否則你將返回對超出范圍的東西的引用(你的tmp )不是一個好主意!

編譯器在讓你知道這一點方面非常有幫助!

我不知道你想聽到什么。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM