【问题标题】:c++ abstract base with datatype will be defined in derived class具有数据类型的 c++ 抽象基将在派生类中定义
【发布时间】:2023-03-25 00:09:01
【问题描述】:

我想要一个基类,其数据类型将在派生类中定义。

伪代码

class Base{
 public:
  void Enroll(vector<int> v){
    feature_list.emplace_back(ExtractFeature1(v));
  }

  vector<double> Compare(vector<int> v){
    FeatureType2 ft2 = ExtractFeature2(v);
    vector<double> scores;
    for (auto &ft1:feature_list){
      scores.emplace_back(Compare(ft1, ft2));
    }
    return scores;
  }

 protected:
  vector<FeatureType1> feature_list;

  virtual FeatureType1 ExtractFeature1(vector<int> v)=0;
  virtual FeatureType2 ExtractFeature2(vector<int> v)=0;
  virtual double Compare(FeatureType1 f1,FeatureType2 f2)=0; 
}

因此,每个派生类都将实现不同的提取和比较特征的方式。

我不知道如何在Base 类中为FeatureType1FeatureType2 设置一些占位符类型,然后强制Derived 类定义它们。任何建议或指导将不胜感激。

【问题讨论】:

    标签: c++ class-design


    【解决方案1】:

    我想要一个基类,其数据类型将在派生类中定义。

    嗯,你不能完全那样做:必须完全定义基类,才能从中派生类。

    不过,您可以使用Curiously-Recurring Template Pattern (CRTP):

    template <typename T>
    class Base {
        using data_type = typename T::data_type;
            // this will be a different type for each T - and
            // we don't need to know it in advance
    
        void Enroll(const vector<int>& v){
            // implementation that can depend on T in many ways.
            // Specifically, you can use `data_type`.
        }
    
        vector<double> Compare(const vector<int>& v){ /* ... */ }
    
        // ...
     };
    
     class SomeDerived : Base<SomeDerived> { /* ... */ };
     class AnotherDerived : Base<AnotherDerived> { /* ... */ };
    

    SomeDerivedAnotherDerived 类实际上没有相同的基类,但它们的基类是相同模板的实例化,因此您可以避免代码重复。并且 - 您拥有使用派生类中定义的类型的“基”类,只要它们以相同的方式定义即可。

    编辑(感谢@Aconcagua):您可能不需要完整的 CRTP。如果您的基类唯一需要知道的关于派生类的信息是数据类型,那么只需在 that 上模板化基类,即

    template <typename DataType>
    class Base {
        using data_type = DataType;
        // ... as before...
    };
    
     class SomeDerived : Base<some_data_type> { /* ... */ };
     class AnotherDerived : Base<another_data_type> { /* ... */ };
    

    【讨论】:

    • 这也是我从一开始就想到的,但也许我们可以没有CRTP:class SomeDerived : Base&lt;SomeFeature&gt; {}; class AnotherDerived : Base&lt;AnotherFeature&gt; {};根据问题,我们可能需要两个特征模板参数?
    • 一开始我确实尝试过使用模板。但是,因为我想使用Base *b = new SomeDerived(); /*..*/ b = new AnotherDerived() 之类的东西。但是 CRTP 对我来说是新的。非常感谢您介绍这一点。
    猜你喜欢
    • 2016-10-26
    • 2023-04-11
    • 2013-06-30
    • 2015-03-23
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    相关资源
    最近更新 更多