【问题标题】:Is it possible to create different derived classes sharing the same methods that operate on member variables unique to each derived class?是否可以创建不同的派生类,共享对每个派生类唯一的成员变量进行操作的相同方法?
【发布时间】:2021-11-28 21:23:29
【问题描述】:

我正在用 C++ 编写一个任意排名的张量(多维数组)类,并希望拥有它的静态和动态内存版本。但是,考虑到底层数据容器会有所不同,我正在努力想一种方法来避免在类的静态/动态版本中重复方法。我希望下面这个最小的例子能说明我的观点:

// Product function
template <typename ...data_type>
constexpr auto Product(data_type ..._values)
{
  return (_values * ...);
}

// Static memory version
template <class t_data_type, unsigned ...t_dimensions>
class StaticTensor
{
  private:
  std::array<t_data_type, Product(t_dimensions...)> Entries; // Store entries as contiguous memory

  public:
  StaticTensor() = default;
  ~StaticTensor() = default;

  void StaticMethod()
  {
    // Some code that operates on Entries.
  }
};

// Dynamic memory version
template <class t_data_type>
class DynamicTensor
{
  private:
  std::vector<t_data_type> Entries;

  public:
  DynamicTensor() = default;
  ~DynamicTensor() = default;

  template <typename ...t_dimensions>
  void Resize(t_dimensions ...dims)
  {
    Entries.resize(Product(dims...));
  }

  void DynamicMethod()
  {
    // Some code that operates on Entries.
  }
};

我已经考虑过基于继承/多态的方法,但似乎我仍然必须在每个专用类中实现单独的方法。理想情况下,我希望所有方法都可以在 std::arraystd::vector 中对底层迭代器进行操作,而不必担心它们属于哪个数据容器。任何人都可以建议我如何去做吗?

【问题讨论】:

    标签: c++ class inheritance polymorphism c++17


    【解决方案1】:

    您可以使用CRTP技术创建TensorBase,然后将*this转换为Derived&amp;以访问派生类的EntriesMethod()内:

    template <class Derived>
    class TensorBase
    {
     public:
      void Method()
      {
        auto& Entries = static_cast<Derived&>(*this).Entries;
        // Some code that operates on Entries.
      }
    };
    

    那么你的StaticTensor/DynamicTensor可以继承TensorBase得到Method()。为了使基类能够访问私有成员,还需要将基类设置为好友:

    // Static memory version
    template <class t_data_type, unsigned ...t_dimensions>
    class StaticTensor
      : public TensorBase<StaticTensor<t_data_type, t_dimensions...>>
    {
      using Base = TensorBase<StaticTensor<t_data_type, t_dimensions...>>;
      friend Base;
     private:
      std::array<t_data_type, Product(t_dimensions...)> Entries;
    
     public:
      StaticTensor() = default;
      ~StaticTensor() = default;
    };
    
    // Dynamic memory version
    template <class t_data_type>
    class DynamicTensor 
      : public TensorBase<DynamicTensor<t_data_type>>
    {
      using Base = TensorBase<DynamicTensor<t_data_type>>;
      friend Base;
     private:
      std::vector<t_data_type> Entries;
    
     public:
      DynamicTensor() = default;
      ~DynamicTensor() = default;
    };
    

    Demo.

    【讨论】:

    • 非常感谢!这对我的问题来说是一个很好的解决方案! :D
    • 只有一个问题 - 模板参数 t_data_type 和 t_dimensions 是否也可以像访问 Entries 一样从 TensorBase 中访问?
    • 需要在派生类中定义using DataType = t_data_type;,然后在基类的Method()中使用using DataType = typename Derived::DataType;
    • 参数包 t_dimensions 是否也可以起别名?
    猜你喜欢
    • 2014-12-01
    • 2017-05-04
    • 1970-01-01
    • 2012-03-14
    • 2022-01-25
    • 2023-01-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    相关资源
    最近更新 更多