在我们的代码中有一个带有虚函数的类层次结构。我们有不同 “图表”根据相同类型的参数产生一组固定的数字。 细节不同,但行为是一样的。
我们对动态多态作为一种模式感到满意,我们并不那么喜欢所有 我们必须用C ++ 11编写的样板代码才能实现它。我大部分都是 对构造函数中的重复感到沮丧。
类层次结构如下所示:
有一个基地,两个中间人和很多孩子。基地和中间人 有非平凡的构造函数,孩子们不需要任何更多的参数。然而,我们 必须在子代中生成构造函数,因为默认构造函数不会 正确构建中间体。
这是代码,仅限于构造函数,析构函数和成员。该
Diagram
课程:
class Diagram {
public:
Diagram(std::vector<CorrInfo> const &corr_lookup)
: corr_lookup_(corr_lookup) {}
virtual ~Diagram() {}
private:
std::vector<CorrInfo> const &corr_lookup_;
};
中级DiagramNumeric<>
类:
template <typename Numeric_>
class DiagramNumeric : public Diagram {
public:
using Numeric = Numeric_;
DiagramNumeric(std::vector<CorrInfo> const &_corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
: Diagram(_corr_lookup),
output_path_(output_path),
output_filename_(output_filename),
Lt_(Lt),
correlator_(corr_lookup().size(), std::vector<Numeric>(Lt, Numeric{})),
c_(omp_get_max_threads(),
std::vector<std::vector<Numeric>>(
Lt, std::vector<Numeric>(corr_lookup().size(), Numeric{}))) {}
private:
std::string const &output_path_;
std::string const &output_filename_;
int const Lt_;
std::vector<std::vector<Numeric>> correlator_;
std::vector<std::vector<std::vector<Numeric>>> c_;
};
其中一个孩子,C2c
:
class C2c : public DiagramNumeric<cmplx> {
public:
C2c(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt);
};
C2c::C2c(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
: DiagramNumeric<cmplx>(corr_lookup, output_path, output_filename, Lt) {}
当我需要在中间体的构造函数中添加另一个参数时,我必须这样做
更改DiagramNumeric<>
声明和每个子声明和定义。
这会使2 * N + 1
个孩子发生N
更改,感觉非常糟糕。
我考虑将struct
设为DiagramNumeric<>::CtorParams
,这只是
通过传递。需要调整C2c
实例化的客户端代码,但是
我们实际上只传递了不同的corr_lookup
参数,其余三个都是
同样的。
是否有一些机制可以用来削减其中很大一部分 样板代码?
答案 0 :(得分:1)
我们对动态多态作为一种模式感到满意,....我是 对构造函数中的重复感到沮丧。
这不是一些c ++ 11错误。 问题直接来自动态多态。尤其是每个儿童班都需要建立其父母。
您拥有的替代方案是依赖注入+静态多态:
Diagram
模板作为参数DiagramNumeric<cmplx>
,而只是接收一个作为参数复制到成员变量。 ( 依赖注入 )你最终会得到
class C2c {
public:
explicit C2c(const DiagramNumeric<cmplx> &diagram_numeric)
: diagram_numeric_(diagram_numeric) {}
private :
DiagramNumeric<cmplx> diagram_numeric_;
};
假设您要添加另一个参数。在最好的情况下,这是依赖类别的O(1)变化。在最坏的情况下,如果你有一个构建函数,例如
,它会回到2 * N + 1更改C2c build(std::vector<CorrInfo> const &corr_lookup,
std::string const &output_path,
std::string const &output_filename,
int const Lt)
{
return C2c(DiagramNumeric<cmplx>(corr_lookup, output_path, output_filename, Lt));
}