【问题标题】:Inheritance and nested class继承和嵌套类
【发布时间】:2020-07-19 17:57:07
【问题描述】:

我正在尝试实现不同版本的数据结构。假设它有一个如下所示的界面(已简化):

template <typename T>
class Base {
 public:
  class Iterator {
    virtual auto operator*() -> T& = 0;
  };

 public:
  virtual auto Find(const T& value) -> Iterator = 0;
}

现在我想继承一个实现它的类:

template <typename T>
class Derived : public Base<T> {
 public:
  class Iterator {
    auto operator*() -> T& override {
      /* ... */
    }
  };

 public:
  auto Find(const T& value) -> Iterator override {
    /* ... */
  };
}

问题是我需要根据Derived 的功能实现Iterator,但是Find 函数的签名因为Derived::Iterator 而停止(应该是Base::Iterator)。有没有办法这样做还是我必须放弃使用接口类?

【问题讨论】:

  • 假设你设法以某种方式实现它。持有Base&lt;int&gt;* pb 指针(指向Derived&lt;int&gt;,或者可能是另一个实现)的调用者将如何使用Find?它会调用auto iter = pb-&gt;Find(42); - 现在呢? iter 能做什么?你的设计没有说明。
  • 抱歉,修复了Iterator 接口。现在调用者可以像这样取消引用iterauto value = *iter;
  • Find 声称按值返回抽象类的实例。这不可能工作,因为不可能创建抽象类的实例。您提出的界面根本无法实现。

标签: c++ templates inheritance nested


【解决方案1】:

据我了解,您要实现的目标与类型擦除或静态多态性有关。您希望 Base::Iterator 是非抽象的通用类型,可以从任何 Derived 实现构造。

这是一个动态解决方案,您可以根据自己的需要进行优化

template<typename T>
struct Base
{
// This is the interface that needs to be implemented by the derrived classe's iterator
    struct IIterator
    {
        virtual T& Get() = 0;
    };
// this is the generalized type that needs to be returned by find()
    struct Iterator
    {
        Iterator(std::unique_ptr<IIterator> impl ):
            _impl(std::move(impl))
        {
        }

        T& operator*() { _impl->Get(); }

        private:
// You can implement small struct optimization by making a byte array big enough
// to store any of the implementations and avoid dynamic memory
        std::unique_ptr<IIterator> _impl;
    };

    virtual Iterator find() = 0;
};

template<typename T>
struct Derived : public Base<T>
{
// Now in derived we implement our iterator
    struct IteratorImpl : Base<T>::IIterator
    {
        IteratorImpl(T* p) : ptr(p) {}

        T& Get() override { return *ptr; }
        T* ptr;
    };

    typename Base<T>::Iterator find() override
    {
        IteratorImpl result(nullptr);
// After finding we need to construct the generalized type from the implementation
        return typename Base<T>::Iterator(std::make_unique<IteratorImpl>( result ));
    }
};

另一种方法是使用模板和 CRTP 来制作静态界面。 CRTP 是一种技术,它涉及使用模板参数将派生类型信息传回基类,并使用该信息基于派生类型定义或查找 Base 迭代器的实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-05-04
    • 1970-01-01
    • 1970-01-01
    • 2011-06-19
    • 2017-06-22
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    相关资源
    最近更新 更多