<分区>
我有一个非常复杂的图形数据结构。为了清楚起见,让我们将其简化为:
class Node;
class AbstractEdge { void foo() {} };
class Edge1: public AbstractEdge { void bar1() {} };
class Edge2: public AbstractEdge { void bar2() {} };
如您所见,我们的图与其他图不同:存在两种边,均继承自 AbstractEdge。此设计无法更改。现在,假设我必须按照以下方式设计两个类:
class OrientedEdge1
{
Edge1 * edge;
bool orientation;
void foo() { edge->foo(); }
void bar1() { edge->bar1(); }
}
class OrientedEdge2
{
Edge2 * edge;
bool orientation;
void foo() { edge->foo(); }
void bar2() { edge->bar2(); }
}
在实践中,OrientedEdge1::foo() 和 OrientedEdge2::foo() 比仅调用单个方法要长得多,但想法是它们是相同的,仅调用从 AbstractEdge 继承的方法。
您会使用什么设计来分解代码?我正在考虑三种方法:
1。使用免费功能
foo_impl(AbstractEdge * edge) { edge->foo(); }
class OrientedEdge1
{
Edge1 * edge;
bool orientation;
void foo() { foo_impl(edge); }
void bar1() { edge->bar1(); }
}
class OrientedEdge2
{
Edge2 * edge;
bool orientation;
void foo() { foo_impl(edge); }
void bar2() { edge->bar2(); }
}
优点:
- 非常简单的解决方案,比根本不分解要好得多。
缺点:
并非所有方法都可以作为自由函数实现。
声明代码仍然重复。
2。使用继承
class AbstractOrientedEdge
{
AbstractEdge * edge;
bool orientation;
void foo() { edge->foo(); }
}
class OrientedEdge1: public AbstractOrientedEdge
{
Egde1 * edge1() { return static_cast<Egde1*>(edge); }
void bar1() { edge1()->bar1(); }
}
class OrientedEdge2: public AbstractOrientedEdge
{
Egde2 * edge2() { return static_cast<Egde2*>(edge); }
void bar2() { edge2()->bar2(); }
}
优点:
更多分解。
我不打算以多态方式使用这两个类,但谁知道呢,也许它们通过继承相关的事实在将来会变得有用。
缺点:
在构造函数/setter 中需要注意强制 OrientedEdge1::edge 始终指向 Egde1*。
不知何故,static_cast 感觉不对。
3。使用模板
template <class EdgeT>
class OrientedEdge
{
EdgeT * edge;
bool orientation;
void foo() { edge->foo(); }
}
class OrientedEdge1: public OrientedEdge<Edge1>
{
void bar1() { edge->bar1(); }
}
class OrientedEdge2: public OrientedEdge<Edge2>
{
void bar2() { edge->bar2(); }
}
优点:
大多数分解。
存储在两个类中的指针具有正确的类型,无需转换。
缺点:
- 需要在 header 中保留共享代码的实现,这会强制包含 AbstractEdge.h(可以通过以前的方法的前向声明来避免)。
问题:您倾向于使用哪种方法?您还有其他解决方案或建议吗?