c++ - 平行继承树,其中一棵树中的类包含另一棵树中的类的容器

标签 c++ inheritance

我真的不知道如何在标题中指定问题,所以这里是它的要点。

我正在编写图形类 Graph、Node 和 Edge,然后将它们子类化为 VisGraph、VisNode 和 VisEdge 以获得可绘制图形(在 C++ 中)。然后我需要将它们进一步子类化为依赖于特定数据的特定类。所以我有很多并行继承:

Graph -- VisGraph -- RouteGraph

Node  -- VisNode  -- RouteNode

Edge  -- VisEdge  -- RouteEdge

这很丑陋,我开始这样做,以便逐步实现功能,但存在很多问题。例如,其中之一是基类具有图中所有 Node 实例的容器。问题是,如果我在 VisGraph 中处理 VisNode 的函数中需要 VisNode 独有的功能,我必须对从基类容器中获取的节点执行 dynamic_cast。

也许我应该写一个“Vis”类来保存一个 Graph 并绘制它? 我发现继承很方便,因为每个节点/边都可以很容易地绘制自己而不是我 在位置等之外存储额外信息,并单独绘制它们。

您有什么建议/设计模式可以使它更优雅吗?

提前谢谢你。

最佳答案

如果有疑问,将模板扔给问题直到它投降:

template <typename N, typename E>
class Graph {
    std::vector<N> nodes;
    std::vector<E> edges;
};

typedef Graph<VisNode, VisEdge> VisGraph;
typedef Graph<RouteNode, RouteEdge> RouteGraph;

您失去了继承性(RouteGraph 不再继承自 VisGraph),但这在 C++ 中对于容器类型是正常的,而 Graph 有点像容器。不过,您可以保留 Node -> VisNode -> RouteNode 之间的继承。

由于节点和边应该是匹配类型,您可以更进一步,为 Graph 提供一个模板参数,它本身是一个包含边和节点类型作为 typedef 的类。不过,我不确定这是否值得。

编辑

既然要连续添加函数,那么可以保留一种继承形式,但失去多态性:

template <typename N, typename E>
class GraphImpl {
    std::vector<N> nodes;
    std::vector<E> edges;
};

template <typename N, typename E>
class VisGraphImpl : public GraphImpl<N, E> {
    // constructors

    // extra functions
};

template <typename N, typename E>
class RouteGraphImpl : public VisGraphImpl<N, E> {
    // constructors

    // extra functions
};

typedef GraphImpl<Node, Edge> Graph;
typedef VisGraphImpl<VisNode, VisEdge> VisGraph;
typedef RouteGraphImpl<RouteNode, RouteEdge> RouteGraph;

不过,可能有更好的方法,将这些额外的函数捆绑到合理的混入中并使用 CRTP:

template<typename Derived>
class VisFunctions {
    void somfunc() {
        myself = static_cast<Derived&>(*this);
        // do stuff
    }
};

然后:

class VisGraph : public Graph<VisNode, VisEdge>, public VisFunctions<VisGraph> {
    friend class VisFunctions<VisGraph>;
};

class RouteGraph : public Graph<RouteNode, RouteEdge>, public VisFunctions<RouteGraph>, public RouteFunctions<RouteGraph> {
    friend class VisFunctions<RouteGraph>;
    friend class RouteFunctions<RouteGraph>;
};

不过,不确定您的实际情况会如何。顺便说一句,如果您不想/不需要额外函数的友元声明,那么您根本不需要将这些额外函数作为成员 - 只需让它们成为采用 VisGraph 或 RouteGraph 参数的自由函数即可。

关于c++ - 平行继承树,其中一棵树中的类包含另一棵树中的类的容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3779489/

相关文章:

c# - 如何从另一个类访问具有 protected 构造函数的类

c# - 继承 : does not contain a definition for and no extension method accepting a first argument

c++ - 如何在 beaglebone black 上用 C++ 创建这么多线程

c++ - 使用比较器网络对固定长度数组进行非常快速的排序

c++ - 为什么我继承的构造函数调用我的基本默认构造函数

python - Python 继承的问题

Java 参数化类警告

python - 在嵌入式 PyQt 应用程序中使用 QThread

c++ - 使用没有代码的静态库时,VC++ 是否添加对 LoadLibrary 的调用?

c++ - 在 C++ 中动态更改对象的基类