继承和嵌套类

Posted

技术标签:

【中文标题】继承和嵌套类【英文标题】: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 声称按值返回抽象类的实例。这不可能工作,因为不可能创建抽象类的实例。您提出的界面根本无法实现。 【参考方案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 迭代器的实现。

【讨论】:

以上是关于继承和嵌套类的主要内容,如果未能解决你的问题,请参考以下文章

从一个嵌套类继承到另一个嵌套类时出错

嵌套类继承错误

为什么嵌套类“继承”?

如何覆盖继承的嵌套类中存在的虚拟方法

Java嵌套类的作用、用法和调用机制是怎么样的?

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