我面临的情况是,我需要运行多个图像处理过滤器
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);
}
}
只需在向量中插入完全初始化的元素,所以
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));