4

プロジェクトの 1 つで 2D マトリックスを使用しています。C++ FAQ Liteで提案されているようなものです。

きちんとしたことは、次のように使用できることです。

int main()
{
  Matrix m(10,10);
  m(5,8) = 106.15;
  std::cout << m(5,8);
  ...
}

今、頂点で構成されたグラフがあり、各頂点には、上記のような 2D マトリックスへのパブリック (例を簡単にするため) ポインターがあります。今、私はそれにアクセスするためのかなり醜い構文を持っています。

(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...

おそらく、演算子のオーバーロードに慣れていないため、ここでいくつかの構文糖衣が欠けています。より良い解決策はありますか?

4

9 に答える 9

4
  1. ポインターの代わりに参照を使用することを検討してください (ただし、null にすることはできず、コンストラクターで初期化できます)。
  2. 2D マトリックスへの参照を返す頂点のゲッターまたはマトリックス ラッパー クラスのインスタンスを作成することを検討してください (ただし、null にすることはできません)。

    sampleVertex.some2DTable()(0,0) = 0;
    sampleVertex.some2DTableWrap(0,0) = 0;
    

しかし、私には、すべてのトラブルを経験することを正当化することは問題ではないように思えます.

于 2009-03-25T14:17:32.823 に答える
2

あなたは基本的にに限定されてい(*sampleVertex.some2DTable)(0,0)ます。もちろん、再装着する必要がない場合は、代わりに実際の値をマトリックスに格納してみませんか?

または、ポインターを非公開にし、アクセサーを作成します (注: 次の例では、EntryTypes のマトリックスを想定しています)。

Matrix& Vertex::GetTableRef() 
{
    return *some2DTable; 
}
// or
Matrix::EntryType& Vertex::GetTableEntry(int row, int col)
{
    return (*some2DTable)(row,col);
}

// way later...
myVertex.GetTableRef()(0,0) = 0;
// or...
myVertex.GetTableEntry(0,0) = 0;

または、クラス Vertex を変更できない場合は、インライン関数を定義してこれを行います。

// in some header file
inline Matrix& GetTableRef(Vertex& v)
{
    return *v.some2DTable;
}

// or you could do this
inline Matrix::EntryType& GetTableEntry(Vertex& v, int row, int col)
{
    return (*v.some2DTable)(row, col);
}


// later...
GetTableRef(myVertex)(0, 0) = 0;
// or
GetTableEntry(myVertex, 0, 0) = 0;

最後に、演算子のオーバーロードを使用する必要がないことを忘れないでください。STL コレクションは、チェックされていない operator[] とは対照的に、チェックされている at() メンバー関数を実装します。境界チェックのオーバーヘッドを気にしない場合、または非標準にしたい場合は、 at() を実装してから を呼び出すだけmyVertex.some2DTable->at(0,0)で、構文上の頭痛の種を少し節約できます。

于 2009-03-25T14:17:42.387 に答える
1

あなたが説明することの苦痛を和らげるC ++構文糖はありません:

(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...

この状況では、グラフがポインターではなく参照を返すようにするか、マトリックスで operator() を呼び出す関数を定義するようにします。

inline matrixType &Matrix::get( int x, int y ){ return operator()(x,y); }

次に、頂点の例の構文はそれほど醜いものではありません。

sampleVertex.some2DTable->get(0,0) = 0;
于 2009-03-25T14:32:05.533 に答える
1

rlbond が推奨するような ref を返す関数を追加します。簡単な修正、またはそのソースを制御できない場合は、次のようにします。

sampleVertex.some2DTable[0](0,0) = 0; // more readable

aが定義されたクラスへのポインタである場合、次が成り立つため、これは実際には同等です。

*a == *(a + 0) == a[0]

comp.lang.c++ に関するこの長い議論を参照してください。同じ問題と適切な回答があります。

于 2009-03-25T15:35:02.573 に答える
0

「sampleVertex.some2DTable」の取得方法を変更して、参照を返すようにします。

それか、自分で参照を作成します。

Matrix& m = *sampleVertex.some2DTable;
m(1,2) = 3;
于 2009-03-25T16:42:08.827 に答える
0

メンバー関数を呼び出すことでMatrix::operator(int、int)を実装し、ポインターを処理するときにその関数を直接使用できます。

class Matrix
{
public:
  float ElementAt( int i, int j ) const { /*implement me*/ }
  float operator() ( int i, int j ) const { return ElementAt( i, j ); }
  ...
};

void Foo(const Matix* const p)
{
  float value = p->ElementAt( i, j );
  ...
}

void Bar(const Matrix& m)
{
  float value = m(i,j);
}
于 2009-03-26T12:38:59.760 に答える
0

手間をかける価値があるかどうかはわかりませんが、次のことができます。

class MatrixAccessor {
private:
  Matrix2D* m_Matrix;
public:
  MatrixAccessor(Matrix2D* matrix) : m_matrix(matrix) { }
  double& operator()(int i, int j) const { return (*m_Matrix)(i,j); }
  Matrix2D* operator->() const { return m_Matrix; }
  void operator=(Matrix2D* matrix) { m_Matrix = matrix; }
};

元のものoperator()が参照を返す場合 (多くの行列クラスと同様)。

次に、その MatrixAccessor を頂点クラスに提供します。

class Vertex {
  Matrix2D* myMatrix;

public:
  MatrixAccessor matrix;
  Vertex(Matrix2D *theMatrix) : myMatrix(theMatrix), matrix(theMatrix) { }
};

次に、次のように記述できます。

Vertex v;
v.matrix(1,0) = 13;
v.matrix->SomeOtherMatrixOperation();

編集

public -pointer のみを提示するソリューションと意味的に同等のソリューションを作成するために、constキーワードを追加しました (このトピックを取り上げてくれた@phresnelMatrix2Dに感謝します) 。

このソリューションの利点は、and の 2 つの非constバージョンを追加operator()()し(つまり、行列は頂点operator->()で変更できません)、それぞれを andを返すように変更することで、constness を行列オブジェクトに転送できることです。constconstconst double&const Matrix2D*

行列オブジェクトへのパブリック ポインターを使用する場合、これは不可能です。

于 2009-03-25T16:09:24.113 に答える
0

これは、コードを変更しない最善の方法です。

//some2DTable is a pointer to a matrix
(*sampleVertex.some2DTable)(0,0)

また、マトリックスへのポインターではなく、some2DTable をマトリックスへの参照にすることもできます。次に、最初のコード スニペットのように構文を簡素化します。

//some2DTable is a reference to a matrix instead of a pointer to a matrix
sampleVertex.some2DTable(0,0)

または、some2DTable を参照へのポインターとして保持し、単純に参照変数を格納して、それをコード ブロックのコンテキストで使用することもできます。

于 2009-03-25T14:11:00.967 に答える