我偶然发现了一个问题(我的任何知识渊博的同事都不知道)如何解决(解决问题)。最终的问题是无法创建虚拟模板功能。我彻底搜查了网,找到了几种处理它的方法,但似乎没有一种适用于我的情况。
我不知道如何描述这种情况,但我会尽我所能并希望它有意义。
问题在于处理两条曲线,每条曲线由一个或多个相同或不同曲线类型的段组成。所以我开始为曲线段创建一个界面,它将与曲线的模板类进行交互(例如,函数与两个不同曲线段之间的交叉点的类型相同):
template<class curve> class curve_segment { // some methods here }
然后,用户可以实现几种类型的曲线,以及适当的函数,具体取决于它将与之交互的曲线。例如,circle
和line
,两者都可以与两者互动:
class line : public curve_segment<line>, public curve_segment<circle> { //... }
class circle : public curve_segment<line>, public curve_segment<circle> { //... }
接下来,我有一个类cell
,它依赖于两个曲线段,以及一个封装它的基类cell_base
:
template<class curve1, class curve2> class cell : public cell_base {
cell_base* up; cell_base* down;
curve_segment<curve1>* segment_x;
curve_segment<curve2>* segment_y;
// some methods that depend on both curves
}
最后,存在这样的单元的2D网格m * n,其中两条曲线由可能不同类型的m和n curve_segments
组成,并且由每个单元中的两个指针保持在一起。
问题开始显示何时将新的curve_segment添加到两条曲线之一。显而易见的解决方案是添加
template<class curve> virtual void add_curve_x(curve_segment<curve> seg) =0;
到cell_base
类,cell
中的实现可以提取另一条曲线的相应段,并向其中添加一个新单元格。例如,如果曲线a
和b
a
表示网格中的x轴,我们要将另一条曲线段添加到曲线a
,我们可以找到在网格的大多数单元格的右侧,在每个这样的单元格的y轴上提取曲线,并从那里和新提供的分段创建一个新单元格,它将附加到右边。
类型擦除不起作用,因为我们需要知道cell
创建时新添加的段的类型(我们需要将两个段的类型作为模板参数提供给{{ 1}} class)。
将模板移动到cell
类也行不通,因为这意味着在每次cell_base
分配时我都必须知道下一个cell
的类型
有解决方法吗?
修改:
如建议的那样,添加curve_segment
方法:
add_curve_x
在这种情况下,template<class curve1, class curve2>
template<class curve>
cell<curve1, curve>* cell<curve1, curve2>::add_curve_x(curve_segment<curve1>* seg) {
return new cell<curve1, curve>(seg, (curve_segment<curve>*)(this->segment_y));
}
必须是seg
类型,必须实现curve
。 curve_segment<curve1>
还必须实施segment_y
。
编辑2 :解释为什么演员阵容
以非粗体矩形表示。在这种情况下,有两条曲线,曲线curve_segment<curve>
包含2个曲线,曲线a
包含3个曲线。类b
必须实现line
以及curve_segment<line>
,而circle也必须实现这两者。现在让我们将另一个贝塞尔曲线段添加到曲线curve_segment<circle>
。课程a
必须实施bezier
和curve_segment<line>
,而curve_segment<circle>
和line
必须实施circle
。
让我们看看我们如何创建粗体三curve_segment<bezier>
的中间部分。我们打个电话
cells
在add_curve_x<bezier>(new bezier(...));
类型的单元格对象上。
参数cell<circle, circle>
将是一个新的seg
对象(可以转换为bezier
),这也是curve_segment<circle>
类型的内容,{{1必须转换为curve
,因为这是它在新创建的单元格中与之交互的曲线类型。
答案 0 :(得分:0)
添加curve_segment_base
:
class curve_segment_base {
// for double dispatching here:
virtual cell_base* add_curve_x(cell_base* cell) = 0;
};
template<class curve>
class curve_segment : public virtual curve_segment_base {
// some specific methods here
// for double dispatching here:
virtual cell_base* add_curve_x(cell_base* cell)
{
// this has to be moved to cpp file due to dependency from cell_base
return cell->add_curve_x(this); // now the correct method from cell is called
}
};
因此,您可以将此方法作为虚拟添加到您的cell_base
class cell_base {
virtual cell_base* add_curve_x(curve_segment_base* seg) = 0;
// methods necessary for double dispatching here:
virtual cell_base* add_curve_x(curve_segment<line>* seg) = 0;
virtual cell_base* add_curve_x(curve_segment<circle>* seg) = 0;
...
};
所以你的方法看起来像是双重调度:
template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment_base* seg) {
return seg->add_curve_x(this);
}
您必须为所有细分实施所有真正的实施方法:
template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment<line>* seg) {
return new cell<curve1, line>(...);
}
template<class curve1, class curve2>
virtual cell_base* cell<curve1, curve2>::add_curve_x(curve_segment<circle>* seg) {
return new cell<curve1, circle>(...);
}