C ++ - 在头文件中解析模板类的循环依赖关系的最佳约定?

时间:2014-07-11 15:46:16

标签: c++ graph header-files circular-dependency

我正在用C ++编写自己的模板化Graph类实现,所以我也在实现模板化的VertexEdge类。因此,实现必须在它们各自的头文件内,而不是在单独的.cpp文件中。 (最佳答案here对我不起作用)

我的Vertex类存储邻域的邻接列表,作为vector的{​​{1}},Edge类存储指向源和目标的指针{{1 s以及边缘的重量。

由于Edge仅存储指向Vertex的指针,因此在Edge中转发声明Vertex类就足够了。然后我可以在Vertex的顶部Edge.h

这是解决#include "Edge.h"Vertex.h类的共同依赖关系的最佳方法吗?用户必须Vertex这两个文件才能使用其中任何一个(即Edge)。

如果用户想要使用#include而不必明确包含Graph.h,反之亦然,该怎么办?我应该在另一个内部转发声明和Vertex吗?

或者我应该在同一个头文件中实现它们吗?

如果有的话,STL中是否解决了这个问题?

这就是我现在所拥有的:

Edge.h:

Edge.h

Vertex.h:

#include

2 个答案:

答案 0 :(得分:0)

  

如果用户想要使用Vertex而不必明确包含Edge.h,反之亦然,该怎么办?

由于您首先要讨论的是设计Graph课程,因此在内部中包含两个标题并没有什么不妥。然后,用户只需#include "graph.h"(或任何您称之为文件的内容),而不是真正考虑它是如何在较低级别设计的。

话虽如此 - 如果你想让你的班级按照现在的方式设计 - 你的解决方案是个好主意。但是,正如评论中已经提到的那样,Vertex不需要拥有它的边缘。也许你应该考虑一个不同的结构:

template<typename vertexType, typename edgeType>
class graph{
    std::map<std::pair<vertexType,vertexType>, edgeType>;
};

请记住,使用此设计,特定方法的编写可能会稍微复杂一些(可能会慢一点)。但是 - 你最终会在这个过程中使用更少的内存。根据您真正想要实现的目标(小尺寸或快速工作),您最终可能会使用不同的图形结构。

答案 1 :(得分:0)

我已经通过将Vertex类与Edge类分离来为解决方案做出妥协,如下所示。

Edge.h:

#ifndef EDGE_H
#define EDGE_H

template <class T> class Edge
{
private:
    T* _source;
    T* _dest;
    long long _weight;

...

};
#endif

Vertex.h中,向量变为std::vector<Edge<Vertex<T> > >。如果需要,可以使用typedef Edge<Vertex<T> > EdgeVertex.h中的公开Graph.h简化这一过程。因此,消除了循环依赖性,并且可以单独使用每个类别&#34;明确地不包括另一个:现在Graph.h取决于Vertex.h,这取决于Edge.h

作为一个侧面说明来解决关于拥有其边缘的顶点的注释:我正在扩展我已经完成的图形类的实现,并且算法将是即插即用的(只需极少的更改)我保持相同/相似的邻接列表结构。