2012-05-01 15 views
0

私はグラフで動作するプログラムを書いています。私は2種類のグラフを取り扱っています:「抽象的なグラフ」は、エッジを持つ抽象的な頂点と、平面の座標x、yを持つ「平面グラフ」です(実際には、複雑な接尾辞zしかし、それは問題ではありません)。C++での抽象/具象グラフの実装について

私の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、複合接辞)コンストラクタに次のような効果があるようにしたい:1. Labelと隣人のリストがVと同じで接辞が与えられたPlanar_Vertexを出力する。これまでのところ、簡単です。 2. Vをこの新しいオブジェクトの基礎となる抽象的な頂点にしたいと思います。言い換えれば、私が書いた私のmain.cppにファイルであれば、たとえば、

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

、私はV2のSET_LABELの使用は()もV1(例えば)に影響することにしたいと思います。このコンストラクタでは、V(メモリ内)のアドレスをPlanar_Vertexのアドレスと同じにします(以前はVに割り当てられていたメモリを解放します)。どうやらメモリ内の変数の位置を変更することはできないので、私は何をすべきか分かりません。私はC + +に比較的新しいですし、私はプレースメントの新しい、std :: move、rvaluesなどについて読んだり読んでいます。誰かが私が望むことをやる方法を見ていますか?

[編集:私はすでに構築されている基本クラスのオブジェクトの上に派生クラスのオブジェクトを構築することができるようにしたい、要約する。]

さて、I以来、皆さんにグラフの実装について多くのことを話しました。私はあなたに残りについてお話したいと考えていましたので、私はあなたにそれについてあなたの意見を与えることができます。明らかに、私の最初の質問に対する答えがすでにクールだと分かっている場合は、次のことを読む必要はありません。つまり、抽象的な頂点で構成される「抽象的なグラフ」と、平面の頂点で構成される平面グラフを扱っていると言いました。ここで

は私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 
}; 

私の考えは、基本クラスのグラフをインスタンス化することはないだろうということですが、私はこれの機能として、「抽象グラフの操作」を実装することができるようになりますAbstract_GraphオブジェクトとPlanar_Graphオブジェクトの両方で動作します。これは純粋に仮想関数get_list_verticesのおかげで可能になりました。これは合理的なやり方ですか?あなたは何をしましたか?

お返事ありがとうございました。

答えて

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; 
} 

をご参照を使用している場合は、それコンストラクタ初期化リストで初期化する必要があります。ポインタを使用すると、初期化の方法に柔軟性がありますが、どこでもヌルポインタが心配される必要があります。

どちらの場合も、頂点がPlanar_Vertexよりも長く存続することを確認する責任があります。

Planar_Vertex –のメンバとしてプレーンVertex(参照またはポインタではありません)を用意し、Planar_Vertexのコンストラクタで初期化し、必要な場所で使用することもできます。あなたのコードでは可能ではありません)。

2番目の部分については、基本的に間違ったことは何も表示されませんが、あなたが投稿したものだけで意見を持つことは難しいです。継承はこれを行う1つの方法であり、もう1つはテンプレートを使用することです。どちらが適切かは、正確な要件(およびこれらの概念に精通しているかどうか)によって異なります。

+0

ありがとうございます。私はあなたのように2つの独立したクラスVertexとPlanar_Vertexを書くことを考えました。しかし、これは私がやりたいことではありません。継承のポイントは、(add_neighborなどのように)抽象関数を1回書くだけで済むからです。さらに、私はそうした方法を実装すれば、私のグラフで同じ問題が発生するでしょう。継承はここでやるべき自然なことだと私は思っていますが、もちろん間違っている可能性があります。テンプレートに関しては、私はそれらについて何も知らない。 – Seub

+0

上記の例は、 'Planar_Vertex:public Vertex'でも同様に動作します。 "Vertex"の上に "/"のまわりに 'Planar_Vertex'を構築したい場合、あなたはそれを見る方法に応じて"できません "または"選択しません "。すべての 'Planar_Vertex'オブジェクトは頂点の上に構築されています - あなたはすでにそれを持っています。しかし、すでに構築されているランダムな頂点の上に 'Planar_Vertex'を構築することはできません。 – Mat

+0

(換言すれば、頂点を使用するあらゆる場所でPlanar_Vertexへの参照またはポインタを使用することができます) – Mat

関連する問題