我想要一个类接口(我们称其为A类),该类接口可以在我的代码中以不同的方式继承和实现,并且该接口包含一些函数,包括stl类型迭代器,该迭代器定义为嵌套类。
我的问题是,每当我尝试继承接口(让我们称为类B)以及迭代器并实现它们时,继承类的开始和结尾都希望使用类型为A :: iterator的迭代器,即使B类中的迭代器继承自A :: iterator。我知道多态仅适用于指针/引用,但是我将如何做到这一点?
我也尝试过与朋友类一起做,但是我真的不知道它们是如何工作的,因为我以前从未使用过它们,所以结果看起来有些混乱。这是一些示例代码(我实际运行的代码)
class A
{
public:
class iterator
{
public:
virtual Entity& operator*() const = 0;
virtual bool operator!=(const iterator) const = 0;
virtual bool valid() const = 0;
virtual iterator& operator=(const iterator& it) = 0;
virtual iterator operator++() = 0;
virtual iterator operator++(int) = 0;
virtual ~iterator() {};
};
virtual int add(const std::vector<std::string>& params) = 0;
virtual int remove(const std::vector<std::string>& params) = 0;
virtual int update(const std::vector<std::string>& params) = 0;
virtual int save(const std::vector<std::string>& params) = 0;
virtual int size() = 0;
virtual typename iterator begin() = 0;
virtual typename iterator end() = 0;
virtual ~A() {}
};
class B: public A
{
private:
std::vector<Entity> elements;
public:
class iterator : public A::iterator
{
private:
std::vector<Entity>::iterator ptr;
B& repo;
public:
iterator(std::vector<Entity>::iterator ptr, B& container) : ptr{ ptr }, repo{ container }{}
Entity& operator*() const override;
bool operator!=(const iterator) const override;
bool valid() const override;
iterator& operator=(const iterator& it) override;
iterator operator++() override;
iterator operator++(int) override;
};
B() : elements{ std::vector<Entity>() } {}
int add(const std::vector<std::string>& params) override;
int remove(const std::vector<std::string>& params) override;
int update(const std::vector<std::string>& params) override;
int save(const std::vector<std::string>& params) override;
int size() override;
typename iterator begin();
typename iterator end();
~B() {};
};
之所以要这样做,是因为我必须创建2个不同的存储库,其中一个使用文件,一个在内存中,并且将来可能需要一个数据库,但是我无法通过继承来获得正确的迭代器它。返回一个std :: vector会快很多,但也有点作弊。编辑:我最终要实现的目标是拥有两个具有相同接口的存储库,并且这些存储库也可以通过它们进行迭代,其中一个在std :: vector上实现,另一个在文件上直接实现。这意味着向量回购的迭代器必须只给我const std :: vector迭代器,而另一个则必须以只读方式打开文件,转到下一行等。我必须使它们与基于循环的范围兼容。
class A
{
protected:
class IterInterface
{
public:
virtual ~IterInterface() = default;
virtual std::unique_ptr<IterInterface> clone() const = 0;
virtual Entity& dereference() const = 0;
virtual void increment() = 0;
virtual bool equal_to(const IterInterface& other) const = 0;
};
virtual std::unique_ptr<IterInterface> begin_impl() const = 0;
virtual std::unique_ptr<IterInterface> end_impl() const = 0;
public:
class iterator
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = Entity;
using reference = Entity&;
using pointer = Entity*;
using difference_type = std::ptrdiff_t;
iterator() = default;
iterator(const iterator& it)
{
if (it.m_impl)
m_impl = it.m_impl->clone();
}
iterator(iterator&&) noexcept = default;
iterator& operator=(const iterator& it)
{
if (it.m_impl)
m_impl = it.m_impl->clone(); // self-assignment-safe
else
m_impl = nullptr;
return *this;
}
explicit iterator(std::unique_ptr<IterInterface> && impl)
: m_impl(std::move(impl)) {}
Entity& operator*() const
{ return m_impl->dereference(); }
iterator& operator++()
{ m_impl->increment(); return *this; }
iterator operator++(int) const
{
iterator copy = *this;
m_impl->increment();
return copy;
}
friend bool operator==(const iterator &it1, const iterator &it2)
{
bool it1_ok = it1.m_impl;
bool it2_ok = it2.m_impl;
if (it1_ok && it2_ok)
return it1.m_impl->equal_to(it2.m_impl);
else
return it1_ok == it2_ok;
}
friend bool operator!=(const iterator &it1, const iterator &it2)
{ return !(it1 == it2); }
};
iterator begin() const
{ return iterator(begin_impl()); }
iterator end() const
{ return iterator(end_impl()); }
// ...
};
class B : public A
{
public:
// ...
private:
std::vector<Entity> elements;
class IterImpl : public IterInterface
{
public:
explicit IterImpl(std::vector<Entity>::iterator viter)
: m_viter(viter) {}
std::unique_ptr<IterInterface> clone() const override
{ return std::make_unique<IterImpl>(m_viter); }
Entity& dereference() const override { return *m_viter; }
void increment() override { ++m_viter; }
bool equal_to(const IterInterface& other) const override
{
if (auto* oimpl = dynamic_cast<const IterImpl*>(&other))
return m_viter == oimpl->m_viter;
// "other" isn't even from a B.
return false;
}
private:
std::vector<Entity>::iterator m_viter;
};
std::unique_ptr<IterInterface> begin_impl() const
{ return std::make_unique<IterImpl>(elements.begin()); }
std::unique_ptr<IterInterface> end_impl() const
{ return std::make_unique<IterImpl>(elements.end()); }
};