0

我正在编写一个适用于图表的程序。我正在处理两种类型的图:“抽象图”,它包含带有边的抽象顶点,以及“平面图”,其中顶点在平面上具有坐标 x,y(实际上我正在使用复杂的词缀 z但这无关紧要)。

我选择在我的 Vertex.h 文件中编写一个(抽象的)Vertex 类和一个派生类 Planar_Vertex,如下所示——这不完全是我的代码,我让它稍微简单一些,并从法语“翻译”它;)

class Vertex
{
public:
    Vertex();
    int get_label();
    void set_label(int label);
    void add_neighbor(int label);
    bool is_neighbor(int label);
    // etc
protected:
    int _label;
    std::vector<int> _list_neighbors;
};


class Planar_Vertex : public Vertex
{
    complex<double> _affix;
public:
    Planar_Vertex();
    Planar_Vertex(Vertex& V, complex<double> affix);
    complex<double> get_affix();
    void set_affix(complex<double> affix);
};

这是我的主要问题。我希望我的 Planar_Vertex(Vertex& V, complex affix) 构造函数具有以下效果: 1. 输出一个 Planar_Vertex,其标签和邻居列表与 V 相同,并且给出了其词缀。到目前为止,很容易。2. 我希望 V 恰好是这个新对象的抽象顶点。换句话说,如果在我的 main.cpp 文件中我写了,说,

Vertex V1;
...
Planar_Vertex V2(V1,z)

那么我希望在 V2 上使用 set_label() 也会影响 V1(例如)。我的看法是,在这个构造函数中,我想说的是:使 V 的地址(在内存中)与构造的 Planar_Vertex 的地址相同(并释放先前分配给 V 的内存)。显然不可能改变内存中变量的位置,所以我不知道该怎么做。我对 C++ 比较陌生,而且我在阅读有关放置 new、std::move、rvalues 等方面迷失了方向。有人知道如何做我想做的事吗?

[编辑:总而言之,我希望能够在已经构建的基类对象之上构建派生类的对象。]

好的,既然我告诉你们那么多关于我的图表的实现,我想我会告诉你们剩下的,所以你们可以给我你的意见,我希望你们不介意。显然,您不必阅读以下内容,如果您知道我的第一个问题的答案,那已经很酷了。所以正如我告诉你的,我们正在处理“抽象图”,它包含抽象顶点,以及平面图,它包含平面顶点。

这是我的 Graph.h 文件的样子:

class Graph
{
public:
    Graph();
    virtual ~Graph();
    virtual std::vector<Vertex*> get_list_vertices();
    void add_edge(int label1, int label2);
    virtual void add_vertex(Vertex&);
    // etc
};

class Abstract_Graph : public Graph
{
    std::vector<Vertex*> _list_vertices;
public:
    Abstract_Graph();
    ~Abstract_Graph();
    std::vector<Vertex*> get_list_vertices();
    void add_vertex(Vertex& V);
    // etc
};

class Planar_Graph : public Graph
{
    std::vector<Planar_Vertex*> _list_planar_vertices;
public:
    Planar_Graph();
    ~Planar_Graph();
    std::vector<Vertex*> get_list_vertices();
    std::vector<Planar_Vertex*> get_list_planar_vertices();
    void add_vertex(Planar_Vertex& V);
    // etc
};

我的想法是基类 Graph 永远不会被实例化,但我将能够实现“抽象图操作”作为这个基类的函数,它们将在 Abstract_Graph 和 Planar_Graph 对象上工作。这要归功于纯虚函数 get_list_vertices。这是一种合理的做事方式吗?你会怎么做?

非常感谢您提前回答。

4

1 回答 1

0

如果我理解你,你可以在 Planar_Vertex 类中保留对 Vertex 对象的引用(或指针)来做你想做的事。
削减演示:

#include <iostream>

struct Vertex {
    int value;
};

struct Planar_Vertex: public Vertex {
    Vertex& vr;
    Planar_Vertex(Vertex& v): vr(v) {}
};

int main()
{
    Vertex v;
    v.value = 1;
    std::cout << v.value << std::endl;

    Planar_Vertex p = Planar_Vertex(v);
    p.vr.value = 2;
    std::cout << v.value << std::endl;
}

如果使用引用,则必须在构造函数初始化列表中对其进行初始化。如果您使用指针,您在初始化它的方式上会有更大的灵活性,但必须担心到处都有空指针。

在这两种情况下,您都有责任确保 Vertex 的寿命超过 Planar_Vertex。

(另一种选择是将普通顶点(不是引用或指针)作为 Planar_Vertex 的成员——您通过 Planar_Vertex 的构造函数对其进行初始化,并在需要的任何地方使用它。这可以满足生命周期的要求,但在你的代码。)

对于您的第二部分,我认为没有任何根本性的错误,但是很难仅对您发布的内容发表意见。继承是一种方法,另一种方法是使用模板。哪一个更合适取决于确切的要求(以及您对这两个概念的熟悉程度)。

于 2012-05-01T05:53:31.883 回答