C++ 使用基类向量自动运行多个派生类,但可以访问派生类属性

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

我面临的情况是,我需要运行多个图像处理过滤器

F1
F2
等,所有这些都源自基类
Filter
,并且每个过滤器都重写其虚拟方法
run()
。每个派生过滤器都有一组不同的参数,
int, double, bool
。我想我会使用
vector<unique_ptr<Filter>>
并将每个
F1
F2
存储在其中,因为它们都源自
Filter
。然后循环向量并运行每个项目的
run()
,这将是每个派生类的覆盖版本。效果很好。

但是!我的问题是如何为每个派生类设置过滤器参数

F1
F2
而不进行转换

理想情况下,我希望编译器能够识别向量的每一项是什么派生类并自行进行转换。但从我迄今为止的研究来看,这是不可能的。

雪上加霜的是,与我的问题类似,通常会得到这样的答复:这不是一个好的设计(例如:如何从 C++ 中的基类访问派生类的属性?) .

所以,我的问题是什么是比这更好的设计?如果不存在,那么在没有这种转换的情况下,如何将向量项识别为派生类指针。

现在我有这样的事情:

// g++ test.cpp && a.out
#include <iostream>
#include <string>
#include <vector>
#include <memory>

class Filter {
  public:
    Filter(void){ std::cout << "Filter::Filter() : called" << std::endl; }
    virtual void run(int x) = 0;
};

class Filters {
  public:
    std::vector<std::unique_ptr<Filter>> f;
};

class F1 : public Filter {
  public:
    void run(int x){ std::cout << "F1::run(): p1=" << myparam1 << std::endl; }
    void param1(int x){ myparam1 = x; }
    int param1(void){ return myparam1; }
  private:
    int myparam1 = 12;
};
class F2 : public Filter {
  public:
    void run(int x){ std::cout << "F2::run(): p2=" << myparam2 << std::endl; }
    void param2(double x){ myparam2 = x; }
    double param2(void){ return myparam2; }
  private:
    double myparam2 = 11.0;
};


int main(void){
  Filters fs;

  fs.f.push_back(std::make_unique<F1>());
  // fails because it is not F1 but Filter class
  //fs.f.back()->param1(200);

  fs.f.push_back(std::make_unique<F2>());
  dynamic_cast<F2*>(fs.f.back().get())->param2(100.0);

  for(std::unique_ptr<Filter> &f : fs.f){
    f.get()->run(10);
  }
}
c++ oop inheritance stdvector downcast
1个回答
0
投票

只需在向量中插入完全初始化的元素,所以

int main()
{
  Filters fs;

  auto f1 = std::make_unique<F1>();
  f1->param1(200);
  fs.f.push_back(std::move(f1));

  auto f2 = std::make_unique<F2>();
  f2->param2(100.0);
  fs.f.push_back(std::move(f2));


  for(std::unique_ptr<Filter> &f : fs.f){
    f.get()->run(10);
  }
}

也许,您可以添加构造函数以允许直接设置这些值:

class F1 : public Filter {
public:
    explicit F1(int value) : myparam1(x) {}
    // ...
};

然后

fs.f.push_back(std::make_unique<F1>(200));
© www.soinside.com 2019 - 2024. All rights reserved.