6

以前はうまく分離されていた 2 つのクラスに問題がありますが、今は結合したいと考えています。

問題の詳細についてはあまり詳しく説明しませんが、次のとおりです。

以前は、3 つの空間位置頂点を含むクラス Triangle がありました。

class Triangle
{
    Vertex a,b,c ; // vertices a, b and c
} ;

プログラムには多くの Triangle インスタンスがあったため、それぞれが頂点の独自のコピーを保持していました。getArea()などのメンバー関数getCentroid()はクラスTriangleで記述され、各Triangleインスタンスには頂点 a、b、および c のコピーがあったため、領域または重心を見つけることは他のクラスに依存しませんでした。あるべき姿!

次に、他の理由から、頂点配列/インデックス バッファー スタイルの表現に移行したいと考えました。Sceneこれは、すべての頂点がオブジェクト内にある単一の配列に格納され、それぞれが頂点自体のコピーではなくTriangle、頂点への参照のみを保持することを意味します。Scene最初は、ポインターに切り替えてみました。

class Scene
{
    std::vector<Vertex> masterVertexList ;
} ;

class Triangle
{
    Vertex *a,*b,*c ; // vertices a, b and c are pointers
    // into the Scene object's master vertex list
} ;

(利点について疑問がある場合は、主に頂点を共有する三角形に関係する理由でこれを行いました。*a が移動すると、その頂点を使用するすべての三角形が自動的に更新されます)。

これは本当に良い解決策だったでしょう!しかし、 std::vector はpointers を無効にし、 class のマスター頂点リストに std::vector を使用していたため、確実に機能しませんでしたScene

したがって、整数を使用する必要がありました。

class Triangle
{
    int a,b,c ; // integer index values
    // into the Scene object's master vertex list
} ;

しかし今、私はこの新しいカップリングの問題を抱えています.それ自身の領域または重心を見つけるために、クラスは以前はアクセスできなかった場所にTriangleアクセスする必要があります. class Scene何かを fsck`d したように見えますが、実際にはそうではありません。

WWYD?

4

7 に答える 7

4

ベクトルへの参照を保持できるように、コンストラクターで三角形にベクトルを渡すことができます。その後、シーンにアクセスする必要も、シーンについて知る必要もありません。

typedef std::vector<Vertex> VertexContainer;

class Scene
{
    VertexContainer  masterVertexList ;  
} ;  

class Triangle  
{  
    // A references to the vertices contained in Scene.
    // A triangle no longer needs to know anything about a scene
    VertexContainer&   vertexListRef;

    // index into vertexListRef of the triangles points.
    VertexContainer::size_type  a;
    VertexContainer::size_type  b;
    VertexContainer::size_type  c;  

    public:
        Triangle(VertexContainer&           masterVertexList,
                 VertexContainer::size_type x,
                 VertexContainer::size_type y,
                 VertexContainer::size_type z)
            :vertexListRef(masterVertexList)
            ,a(x),b(y),c(z)
        {}
};
于 2010-09-06T17:45:34.827 に答える
4

vectorin Scenejust store ポインタも持たないのはなぜですか?

std::vector<Vertex *> masterVertexList;

そうすれば、Triangle引き続き を使用でき、ポインタがのデストラクタVertex *で削除されていることを確認するだけです。Scene

于 2010-09-06T16:28:21.113 に答える
3

あなたのトライアングルは本当にあなたのシーンに依存しているように思えます (その頂点はすべてその特定のシーンのメンバーであるため)。実際、Triangle に必須の Scene* メンバーを与えることになるでしょう。

于 2010-09-06T16:15:41.930 に答える
1

悪くないと思います。Triangle一部の一般性が失われ、 の周辺クラスになりましたSceneが、外部インターフェイスとして使用されない場合 (内部バッファーへのそのようなリンクは使用しないことを示唆しています)、それは単なる自然な進化です。

私の解決策は、ボンネットの下のあなたのものと似ていますが、より多くの砂糖が含まれています.

struct Triangle
{
    Triangle( ... ) { ... }
    Vertex *a(),*b(),*c() ; // trivia: this is valid syntax! Getters adjust…
private:
    size_t ax, bx, cx; // … offsets…
    Scene *client; // … into the Scene object's master vertex list.
} ;

このように、メモリ内のものを再編成する必要はありません。古いコードを適応させるには、検索と置換で実行できるandなどを追加()するだけで済み、オブジェクト指向スタイルが改善されます。->a.a

または、コンストラクターを廃止しprivateて POD にします。

于 2010-09-06T19:20:33.700 に答える
1

頂点リストの最後にのみ追加または削除する場合は、deque代わりに a を使用します。

于 2010-09-06T17:48:02.843 に答える
1

非結合から結合への変更は、可能であれば頂点を共有するという決定の自然な結果です。以前は、各三角形がその頂点を「所有」しており、シーンは (おそらく) 束または三角形を所有していました。

三角形が頂点を共有できるようにすると、その基本モデルが変更されます。頂点が 2 つ以上の三角形間で共有される可能性がある場合、1 つの三角形がその頂点を所有できなくなります。(たとえば、shared_ptrのようなものを使用して) 分散型の共有所有権スキームを持つことは可能ですが、現在行っていることはおそらくより単純です。各頂点にはまだ 1 人の所有者がいますが、所有者は現在では代わりにシーンです。個々の三角形。

三角形は、頂点自体を所有するのではなく、「所有する」コレクション内のいくつかの頂点をグループ化するための便利な方法にすぎないため、三角形とその頂点を所有するコレクションとの間の結合がより緊密であることは驚くことではありません。それを気にするのであれば、共有所有権を非表示にして、少なくとも以前のより疎結合の外観を保持することができます。

一般的な考え方は非常に単純です。三角形の頂点を保持するシーンを各三角形が認識する代わりに、シーン ID と頂点インデックスを組み合わせた頂点プロキシ クラスを作成して、三角形が頂点プロキシ オブジェクトを操作できるようにします。以前は頂点オブジェクトを持っていました。密結合を完全に排除するわけではありませんが、密結合の「知識」を単一のクラスに分離し、疎結合の外観を維持するだけです。

これの明らかな欠点は、頂点プロキシ オブジェクトがかなりの量の冗長データを格納する可能性が高いことです。たとえば、特定の三角形のすべての頂点プロキシは、同じシーンの頂点を明確に表しています。各頂点プロキシのシーン ID を明示的に保存すると、以前は 1 つだったシーン ID のコピーが 3 つ保存されます。これは価値がある場合もあれば、そうでない場合もあります。それが実際の問題である場合は、シーン ID を明示的に保存することを回避する方法を考え出すことができますが、それにはおそらく、言語にとらわれない (それに近い) いくつかのトリックが必要になるでしょう。

于 2010-09-06T17:00:26.850 に答える
0

が 1 つしかないと仮定するとScene、それをシングルトン オブジェクトにして、静的メソッドを介して頂点リストにアクセスできます。

複数のSceneオブジェクトがある場合、それぞれTriangleが正確に 1 つに属しScene、どのシーンに属しているかを「認識」する必要があります。したがって、各 Triangle をScene参照で初期化し、クラス メンバーとして格納する必要があります。

于 2010-09-06T16:15:58.553 に答える