类继承层次结构设计问题
a class inheritance hierarchy design issue
我有以下图形的类层次结构:
typedef vector<int> ArrayI;
typedef vector<Array<long>> Mat2DB;
typedef vector<ArrayI> adjList;
class baseGraph {
int nodes;
ArrayI degree;
//some member functions.
}
class matGraph: public baseGraph {
Mat2DB matrix;
//member functions.
}
class lMatGraph: public matGraph {
ArrayI labels;
//member functions.
}
class listGraph: public baseGraph {
adjList list;
//member functions.
}
class lListGraph: public listGraph {
ArrayI labels;
//member functions.
}
现在在这个类中,我有许多其他函数,大部分是虚拟的,这样当我在使用基类指针的同时调用正确的函数时。
例如,我有一个函数sssp(int node)
,它实现了单源最短路径。CCD_ 2和CCD_ 3分别是图的邻接矩阵表示和邻接列表表示。现在不需要更改这些图的标记版本的定义,所以我不需要在lListGraph
和lMatGraph
中再次定义这些函数
现在我遇到的唯一问题是lListGraph
和lMatGraph
类中的setLabel(const ArratI &)
。我需要这个函数是虚拟的,这样它就可以通过基类指针来调用,但同时我没有任何东西,比如类matGraph
和listGraph
的标签。
我不知道我的设计层次结构是否正确,但它对我来说似乎很直观。所以任何关于它的评论都是好的。我能用setLabel
函数做什么。有这样一个函数可以吗(对我来说,这看起来像是一种变通方法,所以这个问题)或者我需要重新考虑我的类层次结构。
附言:如果有一些书可以让我练习这样的设计问题,我也会很高兴的。我碰到这些熟食店,不知道该怎么办。
编辑:
类图的使用用于另一个类clustering
,其中我有一个成员baseGraph *graph
,即
class clustering {
baseGraph *graph;
}
我将指向基类的指针存储在这里,这样我就可以使用class graph
中的不同算法(实现为函数)。对于集群类,它再次取决于我想要使用什么类型的图。
也许是这样?
typedef vector<int> ArrayI;
typedef vector<Array<long>> Mat2DB;
typedef vector<ArrayI> adjList;
class baseGraph {
int nodes;
ArrayI degree;
virtual void sssp(int node);
//some member functions.
}
class labeledGraph: public virtual baseGraph {
ArrayI labels;
virtual void setLabel(const ArratI &);
//member functions.
}
class matGraph: public virtual baseGraph {
Mat2DB matrix;
//member functions.
}
class lMatGraph: public virtual matGraph, public virtual labeledGraph {
//member functions.
}
class listGraph: public virtual baseGraph {
adjList list;
//member functions.
}
class lListGraph: public virtual listGraph, public virtual labeledGraph {
//member functions.
}
我在这里假设,当你们本应该从baseGraph(typeo)继承时,你们却错误地从图继承了——即使不是,它也会归结为同一点。
还有粗略的编码,如果你有问题或有错误,请随时询问。
您说setLabel
应该通过基类指针调用,所以这必然意味着它应该在基类中声明,即使这没有意义。您可以通过两种可能的方式为未标记的图实现setLabel
:
- 什么都不做-只需忽略设置标签的请求
- 抛出一个异常(例如
abort
)-可能出了问题,所以用户应该知道
每种方法都是一种变通方法,所以您应该考虑为什么应该通过基类指针调用setLabel
,并可能更改此决定。我希望,如果你的算法真的需要一个带标签的图,可以使用适当的类型而不是基类类型,这样你就不需要对基类进行任何攻击。
请注意,如果你不断地向基类中添加与每个派生类相对应的东西,那么你最终会在基类中遇到很多麻烦——这不好!
此外,以下内容可能会解决您使用setLabel
的问题,并使您的类层次结构"更健康"。
考虑将class matGraph
0等基本算法从类声明中移除,使它们重载独立函数,而不是成员函数。通过这种方式,您也不需要在基类中声明sssp
。如果你采用这个准则,当你实现一个新的算法时,编译器会检查所有的函数调用,如果缺少一个,就会发出错误(这比崩溃或得到错误的结果要好)。
class baseGraph {
int nodes;
ArrayI degree;
// a minimum number of member functions (e.g. getNode; getEdges)
}
class matGraph: public graph {
Mat2DB matrix;
}
class lMatGraph: public matGraph {
ArrayI labels;
void setLabel(const ArrayI &);
}
int sssp(const matGraph& graph, int node)
{
// Some code
}
int sssp(const lMatGraph& graph, int node)
{
// Some code; here you can use labels
}
这一点在《有效C++》一书中进行了讨论(有效C++第23项:与成员函数相比,更喜欢非成员非好友函数)
这一切都归结为一个简单的选择。如果我试图在图中设置一个实际上不支持标签的标签,会发生什么?
- 什么都没有(尝试可能会被记录,但会被忽略)
- 灾难性的失败
- 我甚至不能尝试(编译器不应该让我)
就是这样。这些都是你的选择。
前两个选项很简单,只需编写一个报告错误(记录错误或引发异常)的虚拟函数。
第三个很有趣。这意味着根本没有相应的虚拟功能。不在你的类中,也不在任何基类中。这违背了你的设计,但你的设计并不一定完美。
那么你该如何设定一个标签呢?通过一些不是指向基类的指针:)它可以是指向另一个基类的指针(mixin——您使用多重继承为图添加标记功能)。或者,您可以将设计模板化,这样层次结构就不会真正重要,并且您总是静态地知道对象的派生类型最多。
- 如何重构类层次结构以避免菱形问题
- 设计将引用元素移动到开头的数据结构.C++
- 包含矢量指针的结构的内存释放问题
- 在类中返回结构时出现问题
- 我对数据结构、双向链表有一些问题
- C++模板类中结构的编译器问题
- 我的超类中的模板问题与结构定义
- 需要为 C++ 中的以下问题设计递归算法
- 将字符数组转换为结构时出现问题. 结构的字符数组变量溢出
- 模板图的设计问题采用不同的结构
- 桌面计算器出现问题.C++程序设计语言
- 多种搜索组合的数据结构设计
- 使用基对象修改/访问派生类的信息的有问题的设计
- 类层次结构设计,避免从基类到派生类的向下转换
- C++类层次结构设计选择
- 类继承层次结构设计问题
- 输入需要我的程序结构/设计
- 通信b/w两个线程在一个公共的数据结构.设计问题
- 类/结构设计;继承与前向声明
- C++数据结构设计:具有不同领域和功能的儿童