[英]C++ Templated Interface for a List ADT with iterators Implementation
我想为 List ADT 提供一个接口,它为用户提供迭代器。 目前我有以下迭代器:
template <typename D>
class IIterator
{
public:
virtual D &operator*(void) = 0;
virtual IIterator &operator++(void) = 0;
virtual bool operator==(const IIterator &rhs) const = 0;
virtual bool operator!=(const IIterator &rhs) const = 0;
virtual IIterator &operator--(void) = 0;
};
这是 List 接口,它使用上面的迭代器接口:
# include "IIterator.hpp"
template <typename D>
class IList
{
public:
virtual IIterator<D> begin(void) const = 0;
virtual IIterator<D> end(void) const = 0;
virtual void insertFront(const D &e) = 0;
virtual void insertBack(const D &e) = 0;
virtual void insert(const IIterator<D> &p, const D &e) = 0;
virtual void eraseFront(void) = 0;
virtual void eraseBack(void) = 0;
virtual void erase(const IIterator<D> &p);
};
我可以放弃迭代器接口,赋值不需要它,但是List必须实现一个纯虚拟接口。 问题是,如果我丢弃IIterator
,我不知道是否可以再在其中包含IList::insert()
和IList::erase()
,因为它们不仅采用模板参数,还采用 Iterator在继承接口的类中实现。
以下 List 实现继承自IList
并使用双向链表。 它不编译:
template <typename D>
class NodeList : public IList<D>
{
private:
struct Node
{
D data;
Node *prev;
Node *next;
};
public:
class Iterator : public IIterator<D>
{
public:
D &operator*(void);
bool operator==(const IIterator<D> &p) const;
bool operator!=(const IIterator<D> &p) const;
Iterator &operator++(void);
Iterator &operator--(void);
private:
Iterator(Node *node);
Node *_ptr;
};
NodeList(void);
~NodeList(void);
NodeList(const NodeList ©);
NodeList &operator=(const NodeList &rhs);
int size(void) const;
bool empty(void) const;
IIterator<D> begin(void) const;
IIterator<D> end(void) const;
void insertFront(const D &e);
void insertBack(const D &e);
void insert(const Iterator &p, const D &e);
void eraseFront(void);
void eraseBack(void);
void erase(const Iterator &p);
private:
int _n;
Node *_header;
Node *_trailer;
};
它输出以下错误:
./../../libft/NodeList.hpp:52:11: error: 'NodeList<int>::insert' hides overloaded virtual function [-Werror,-Woverloaded-virtual]
void insert(const Iterator &p, const D &e);
^
main.cpp:27:17: note: in instantiation of template class 'NodeList<int>' requested here
NodeList<int> seq2;
^
./../../libft/IList.hpp:26:18: note: hidden overloaded virtual function 'IList<int>::insert' declared here: type mismatch at 1st parameter
('const IIterator<int> &' vs 'const NodeList<int>::Iterator &')
virtual void insert(const IIterator<D> &p, const D &e) = 0;
^
子类型多态性不是让IList
接口知道NodeList<int>::Iterator
是IIterator<int>
的子类,因此虚函数insert()
不是隐藏的而是正确重载的? (关于erase()
输出相同的错误)
我相信有一个可怕的设计缺陷,你能告诉我什么可以更换,返工以及我如何才能达到所需的结果?
这里的一般设计和代码都有很多问题和注意事项,但让我们关注您提出的具体问题:
如果基类的方法按value返回IIterator<D>
,那么这是允许子类为其重载返回的唯一类型。
你“可以”让基类返回一个指向IIterator<D>
的指针,并在重载中实例化适当的子类,但是......
虚拟重载运算符处理起来非常痛苦,因此如果您想维护感觉像指针的迭代器,返回一个通用的类型实际上是一件非常好的事情。
相反,您应该使用 pimpl 模式将当前类的实现细节隐藏在迭代器的成员中,同时保持迭代器的值类型。
它大致如下所示:
template <typename D>
class Iterator
{
public:
class Impl {
public:
virtual D* get() = 0;
virtual void inc() = 0;
virtual void dec() = 0;
};
explicit Iterator(std::unique_ptr<Impl> impl)
: impl_(std::move(impl)) {}
D& operator*() { return *impl_->get(); }
Iterator& operator++() { impl_->inc(); return *this; }
Iterator& operator--() { impl_->dec(); return *this; }
bool operator==(const Iterator& rhs) const {
return impl_->get() == rhs.impl_->get();
}
// Modern C++ (C++-20 and up) synthesizes operator!=() from operator==().
private:
std::unique_ptr<Impl> impl_;
};
template <typename D>
class NodeList
{
// ...
private:
class IteratorImpl : public Iterator<D>::Impl
{
public:
D* get() override;
void inc() override;
void dec() override;
private:
Iterator(Node* node);
Node* _ptr;
};
public:
Iterator<D> begin() const override {
return Iterator<D>{std::make_unique<Iterator>(this)};
}
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.