我们说我有三个课程,Solid
,Face
和Edge
定义如下:
class Solid{
public:
// perform an action on a single edge.
void addFillet(int edgeNum);
// perform an action on a single face
void addBore(int faceNum);
// perform an action on all faces and edges
void move(Pos newPosition);
private:
std::vector<Edge*> edges;
std::vector<Face*> faces;
};
class Face{
public:
// will modify a subset of edges
virtual void changeHeight(int newHeight) = 0;
private:
int myNum;
std::vector<Edge> edges;
}
class Edge{
public:
virtual void changeLength(int newLength) = 0;
private:
int myNum;
int length;
}
在此示例中,Solid
管理了一个&#39;超集&#39; Edge
的。{ Face
管理的每个Solid
都有一个&#39;子集&#39; Solid.edges
。此外,任何两个Solid.faces
可能有一个共同的Edge
。
我的问题:是否有任何设计模式或一般面向对象的原则来处理这样的情况?如何管理Solid.edges
和Face.edges
之间的关系?更具体地说
答案 0 :(得分:0)
有很多方法可以管理这些种类的关系,但是如果你想要效率并希望在边缘之间共享顶点并在面之间共享边缘,那么我建议你的Solid
应该拥有{{1}的完整列表}和Vertex
。
然后Edges
对其顶点有一些非拥有的引用,Edge
对它的边有一些非拥有的引用。那些非拥有引用可能类似于指针,但是你必须小心,不要通过重新分配主要的顶点或边缘列表来使这些指针无效。如果您存储索引则更安全。但这确实意味着你必须引用Face
来找出顶点/边缘索引所指的内容:
Solid
另一种方法是将class Solid {
std::vector<Vertex> vertices;
std::vector<Edge> edges;
std::vector<Face> faces;
public:
Solid(std::vector<Vertex> vertices) : vertices(std::move(vertices)) {}
void addEdge(int vertex_index1, int vertex_index2) {
edges.emplace_back(vertex_index1, vertex_index2);
}
void addFace(std::vector<int> edge_indices) {
faces.emplace_back(std::move(edge_indices));
}
const Vertex &getVertex(int vertex_index) const { return vertices[vertex_index]; }
const Edge &getEdge(int edge_index) const { return edges[edge_index]; }
};
class Edge {
int vertex_first;
int vertex_second;
public:
Edge(int vertex_first, int vertex_second)
: vertex_first(vertex_first), vertex_second(vertex_second) {}
const Vertex &getVertexFirst(const Solid &solid) const {
return solid.getVertex(vertex_first);
}
const Vertex &getVertexSecond(const Solid &solid) const {
return solid.getVertex(vertex_second);
}
};
class Face {
std::vector<int> edge_indices;
int getEdgeIndex(int face_edge_index) const {
return edge_indices[face_edge_index];
}
public:
Face(std::vector<int> edge_indices) : edge_indices(std::move(edge_indices)) {}
const Edge &getEdge(int face_edge_index, const Solid &solid) const {
return solid.getEdge(getEdgeIndex(face_edge_index));
}
};
用于std::shared_ptr
和Edge
,但是您必须为动态内存分配和较差的数据位置付费。
为了更好的封装,在Vertex
和Solid
内存储Face
的反向引用很有诱惑力。您可以这样做,但Edge
和vector
的{{1}}实际上包含了许多重复指针。如果这种封装对你很重要,我建议你创建一些包装类来处理包含原始边/面对象的边和面,以及对Face
的反向引用。