【发布时间】:2012-10-08 06:02:36
【问题描述】:
我偶然发现了一个我(我的任何知识渊博的同事也不知道)知道如何解决(解决)的问题。最终的问题是无法创建虚拟模板功能。我已经彻底搜索了网络,找到了几种处理它的方法,但似乎没有一种适用于我的情况。
我不知道如何简短地描述这种情况,但我会尽力而为,希望它有意义。
问题是处理两条曲线,每条曲线由一个或多个相同或不同曲线类型的段组成。因此,我开始为曲线段创建一个接口,其中包含将与之交互的曲线的模板类(例如,函数与两个不同曲线段之间的交点类型相同):
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
}
最后,有一个由 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 时新添加的段的类型(我们需要将两个段的类型作为模板参数提供给 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 也必须实现 curve_segment<curve>。
编辑 2:解释为什么演员在那里
以非粗体矩形为例。在这种情况下,有两条曲线,曲线 a 有 2 段,曲线 b 有 3 段。类line 必须实现curve_segment<line> 和curve_segment<circle>,并且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>),这也是curve 类型,segment_y 必须转换为@987654369 @,因为这是它在新创建的单元格中与之交互的曲线类型。
【问题讨论】:
-
不清楚您要做什么。请在
cell中展示add_curve_x的具体实现(想象一下允许模板虚函数)。 -
仍然不清楚......这个演员在那里做什么?您可以将任何曲线段转换为任何其他曲线段吗?
-
一条曲线可以实现多个不同参数的
curve_segments。实现取决于哪种曲线可能相互影响。在这种情况下,单元格中的曲线与curve1和curve2交互,但是当我们添加不同类型的曲线段(curve)时,segment_y也必须与那个交互。想象一下,你有一条由两条直线和一个圆组成的曲线,第二条由一条贝塞尔曲线和一条圆和一条直线组成。然后一切都必须能够与一切互动。 -
最后我总是可以强制所有曲线段为同一类型并且没有这个问题,但这会大大降低有用性。
-
如果您致电
cell<line, circle>::add_curve_x<bezier>,演员将尝试将curve_segment<circle>*转换为curve_segment<bezier*>。因为这两个类不相关,所以这将作为reinterpret_cast工作,并产生未定义的行为。
标签: c++ templates virtual-functions