0

行列を操作する独自のメソッドを追加するために、IntegerMatrix クラスを作成しました。今、私はこのような関数を書きました:

IntegerMatrix** IntegerMatrix::multiplyMatrix(IntegerMatrix** table2)

(4x4 2D 配列へのポインターの巨大な配列を保持しているため、これは二重ポインターです。) したがって、次のように簡単に実行できます。

matrix1.multplyMatrix(matrix2)

1 つの小さな問題は、*自分のクラスに対して定義されていないことです。そこで、この演算子をオーバーロードして、次のようなことができると考えました。

sum += this->table[i][k] * table2[k][j];

しかし、次のように定義されているオーバーロードされた演算子で正しいiとを取得するにはどうすればよいですか。k

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & k);

私が今理解できない唯一の問題は、正しい値を取得する方法ですか?

編集:

これを書き直したところ、次のようになりました。

IntegerMatrix IntegerMatrix::operator*(const IntegerMatrix & table2)
{
    int i, j, k;
    int sum;
    IntegerMatrix * result = new IntegerMatrix(SIZE);

    for (i = 0; i < SIZE; i++) {
        for (j = 0; j < SIZE; j++) {
            sum = 0;
            for (k = 0; k < SIZE; k++) {
                sum += this->table[i][k] * table2[k][j];
            }
            result[i][j] = sum;
        }
    }
    return *result;

}

[] でエラーが発生します。

Binary '[' : 'IntegerMatrix' does not define this operator or a conversiont o a type acceptable to the predefined operator.
4

3 に答える 3

1

私はあなたの質問を理解していませんが、行列の乗算が通常どのように機能するかの簡単なデモを次に示します。

class IntegerMatrix {
    int table[3][3];

public:
      IntegerMatrix& operator*=(const IntegerMatrix& rhs) {
           //multiply table by rhs.table, store in data.
           return *this;
      }
};
IntegerMatrix operator*(IntegerMatrix lhs, const IntegerMatrix& rhs)
{return lhs*=rhs;} //lhs is a copy, so we can alter and return it

あなたの編集のために

あなたはコードを持っています

IntegerMatrix * result = new IntegerMatrix(SIZE); //pointer to an IntegerMatrix
...
result[i][j] = sum; //assign sum to the jth index of matrix # i

実際には、あなたが望んでいたと思います

result->table[i][j] = sum; //sum to the ixj index of the result matrix.

newまた、 はあるが がないため、関数は漏れやすいですdelete。新しいものは必要ないので、これは簡単に修正できます。(あなたは Java または C# のバックグラウンドを持っていますか?)

IntegerMatrix result(SIZE);
...
        result[i][j] = sum;
...
return result;

上記のすべてとは関係ありませんが、実際には[]整数行列に演算子を提供したい場合があります。

class row {
    int* data;
    int size;
public:
    row(int* d, int s) :data(d), size(s) {}
    int& operator[](int offset) {
        assert(offset<size);
        return data[offset];
    }
};

row operator[](int column) {
    assert(column<SIZE); 
    return row(table[column], SIZE);
}

そして、これにより次のように書くことができます:

IntegerMatrix result;
result[i][j] = sum;
于 2012-10-08T19:29:21.203 に答える
1

Cargo-Cult プログラミングの意味で、いくつかのアーティファクトを引き継いでいる可能性があります。:-/

例:私は**あなたのプロトタイプのmultiplyMatrixの二重間接参照( )がそこにあると推測しています。これは、どこかで整数の多次元配列を見たからです...次のようなもの:

void printMatrix(int ** myMatrix, int rows, int columns);

二重間接参照は単なるポインターからポインターへのポインターです。これは、低レベルの C スタイルの 2D 配列をパラメーターとして渡すという特定の実装ポイントを達成する方法です。しかし、たまたま Matrix を表す抽象クラスを操作している場合は、常にこれに取り組む必要があるわけではありません。したがって、行列のサイズとデータ自体を IntegerMatrix クラス内にカプセル化したら、次のようなことは必要ありません。

void printMatrix(IntegerMatrix ** myMatrix);

次のように、データをカプセル化するクラスへの単純な参照を渡したいと思うでしょう:

void printMatrix(IntegerMatrix const & myMatrix);

少なくとも演算子のオーバーロードを実装するためにそれを使用している場合は、実際には乗算関数から新しい行列を返す必要がありますa * b;. (できますが、すべきではありません。) したがって、マトリックス値のインスタンスを返すかどうかを選択する必要があります。

IntegerMatrix IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

...または新しいオブジェクトへのポインターを返す:

IntegerMatrix * IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

関数内のローカル変数から値を返すと戻り時にコピーを作成する必要があるため、ポインタによる戻りは歴史的に多くのライブラリで選択されてきました。ポインターを返すのは高速ですが (32 ビット/64 ビットの数値を 1 つだけ「コピー」します)、オブジェクトのインスタンスとその中の大きなデータ ブロックをコピーするのは低速です。deleteそのため、多くのライブラリはどこでも Matrix ポインターを使用するだけです...最終的にオブジェクトに対する責任が誰にあるのかを知るのが難しくなるという問題があります。スマート ポインターは、これを確実にする 1 つの方法です。

unique_ptr<IntegerMatrix> IntegerMatrix::multiplyMatrix(IntegerMatrix const & rhs);

しかし、C++11 には、ごちゃごちゃせずに同じくらい高速に動作するための巧妙な機能があります。関数から値によって何かを返し、コンパイラーが値が再び使用されないことを確信している場合 (スコープ外になるため)、ポインターと同じくらい速く「移動」できます。これには、 RValue 参照によるムーブ構築をサポートする必要があり、それにはあらゆる種類のトリッキーがあります。

本当にニュアンスがたくさんあります。教育的な演習としてこれを行っている場合は、すぐに火の中に飛び込むのではなく、ゆっくりとすべてのステップを説明するチュートリアルを実行することをお勧めします. また、マトリックス内で低レベルの C 配列と動的割り当てを使用している場合は、それらをstd::vectorofに変更しますstd::vector

于 2012-10-08T19:56:16.697 に答える