有没有办法在其子级中修改嵌套类的实现?

问题描述 投票:0回答:2

我想要一个类接口(我们称其为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迭代器,而另一个则必须以只读方式打开文件,转到下一行等。我必须使它们与基于循环的范围兼容。

c++ inheritance polymorphism inner-classes
2个回答
0
投票
我设法通过返回对迭代器而不是对象的引用来直言不讳地解决了这个问题。因此,我始终必须在主函数中保留一个可以引用和返回的指针,但至少它可以工作。正如有人在评论中提到的那样,问题是:多态仅适用于指针和引用。

0
投票
似乎您正在寻找一种类型擦除:一种类型,它支持不同的实现,但是可以被其他代码用作单个类型,因为可以复制该类型,而不仅仅是指针和引用,等等。通常的设置方法是非多态类,它包含一个指向多态接口的指针:

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

© www.soinside.com 2019 - 2024. All rights reserved.