宣言時に値を指定できるようにしましょう.
その場合は引数ありのコンストラクタを作ります.
後は関数と同様に実装を書きます.なお,コンストラクタは返り値はありません.
その場合は引数ありのコンストラクタを作ります.
class Matrix2x2 { public: Matrix2x2(); // 引数なし Matrix2x2(double *data); Matrix2x2(double d00, double d01, double d10, double d11); // 以下,前回と同じ };
後は関数と同様に実装を書きます.なお,コンストラクタは返り値はありません.
Matrix2x2::Matrix2x2(double *data) { for(int i = 0; i < 4; ++i) { mat[i] = data[i]; } } Matrix2x2::Matrix2x2(double d00, double d01, double d10, double d11) { mat[0] = d00; mat[1] = d01; mat[2] = d10; mat[3] = d11; }
Matrix2x2を既にある別のMatrix2x2で初期化できるようにしましょう.
これにはコピーコンストラクタというものを使います.
コピーコンストラクタは引数にMatrix2x2とすればよいです.
以上の引数ありのコンストラクタ,コピーコンストラクタにより,下記のような初期化が可能になります.
これにはコピーコンストラクタというものを使います.
コピーコンストラクタは引数にMatrix2x2とすればよいです.
class Matrix2x2 { public: Matrix2x2(Matrix2x2 const& other); }; Matrix2x2::Matrix2x2(Matrix2x2 const& other) { for(int i = 0; i < 4; ++i) { mat[i] = other.mat[i]; } }
以上の引数ありのコンストラクタ,コピーコンストラクタにより,下記のような初期化が可能になります.
Matrix2x2 a(1.0, 2.0, 3.0, 4.0); Matrix2x2 b(a); Matrix2x2 c = b; // 初期化の場合のみ
intやdouble型では演算子+や*などを使って,足し算や掛け算をすることができます.
また=を使って代入もできます.C++には演算子のオーバーロードという仕様があり,自作クラス用に演算子の振る舞いを定義することができます.
逆行列には独自のルールで!演算子を使うことにします.
また=を使って代入もできます.C++には演算子のオーバーロードという仕様があり,自作クラス用に演算子の振る舞いを定義することができます.
逆行列には独自のルールで!演算子を使うことにします.
class Matrix2x2 { public: Matrix2x2& operator=(Matrix2x2 const& other); // 代入 Matrix2x2 operator*(Matrix2x2 const& right) const; // 積 Matrix2x3 operator!() const; // 逆行列 }; Matrix2x2& Matrix2x2::operator=(Matrix2x2 const& other) { for(int i = 0; i < 4; ++i) { mat(i) = other.mat(i); } return *this; } Matrix2x2 Matrix2x2::operator*(Matrix2x2 const& other) const { return this->Multiply(other); // 既に積の関数があるのでそれを使う. } Matrix2x2 Matrix2x2::operator!() const { return this->Inverse(); // 同上 }
Set/Getについては()演算子をオーバーロードして要素にアクセスできるようにしましょう.
さて,何度かでてきていますが,double&の&は参照と言います.参照というのは別名(エイリアス)とも言い,コピーではなくオリジナルと同一です.
PCでいうとコピーではなく,ショートカットを作るようなものです.
ワードファイルがあり,コピーして,コピーしたものを変更してもオリジナルは変わりませんが,
ショートカットを作って,ショートカットから起動して変更した場合はオリジナルが変更されるのと同じです.
&の無い返り値は値返しといい数値のコピーが返されます.
単なる数値なので代入,つまりSetはできません.
参照返しの場合,mat[x]を返します.値ではなくその値の場所を返します.
どのように使えるか見てみましょう.
よって,Multiplyのコードを見やすいものに変更することができます.
では前回のmainを今回の実装で書き換えてみましょう.
class Matrix2x2 { public: double& operator()(int row, int col); }; double& Matrix2x2::operator()(int row, int col) { return mat[2*row+col]; }
さて,何度かでてきていますが,double&の&は参照と言います.参照というのは別名(エイリアス)とも言い,コピーではなくオリジナルと同一です.
PCでいうとコピーではなく,ショートカットを作るようなものです.
ワードファイルがあり,コピーして,コピーしたものを変更してもオリジナルは変わりませんが,
ショートカットを作って,ショートカットから起動して変更した場合はオリジナルが変更されるのと同じです.
&の無い返り値は値返しといい数値のコピーが返されます.
単なる数値なので代入,つまりSetはできません.
参照返しの場合,mat[x]を返します.値ではなくその値の場所を返します.
どのように使えるか見てみましょう.
Matrix2x2 a(1.0, 2.0, 3.0, 4.0); std::cout << a(0,0) << std::endl; // Get(0,0)と同じ a(0,0) = 2.0; //左辺はa::mat[0]への参照なので,mat[0]に2.0を代入できる.Set(0, 0, 2.0)と同じ
よって,Multiplyのコードを見やすいものに変更することができます.
Matrix2x2 Matrix2x2::Multiple(Matrix2x2 const& other) const { Matrix2x2 result; result(0,0) = this->Get(0,0)*other.Get(0,0)+this->Get(0,1)*other.Get(1,0); result(0,1) = this->Get(0,0)*other.Get(0,1)+this->Get(0,1)*other.Get(1,1); result(1,0) = this->Get(1,0)*other.Get(0,0)+this->Get(1,1)*other.Get(1,0); result(1,1) = this->Get(1,0)*other.Get(0,1)+this->Get(1,1)*other.Get(1,1); return result; }
では前回のmainを今回の実装で書き換えてみましょう.
int main() { Matrix2x2 mat(1, 2, 3, 4); Matrix2x2 inv_mat = !mat; std::cout << "mat = " << std::endl; mat.PrintMatrix(); std::cout << "inv_mat = " << std::endl; inv_mat.PrintMatrix(); Matrix2x2 mul_mat = mat * inv_mat; std::cout << "mul_mat = " << std::endl; mul_mat.PrintMatrix(); // 追加.一気に逆行列と掛け算ができます Matrix2x2 mul_mat2 = mat * !mat; std::cout << "mul_mat2 = " << std::endl; mul_mat2.PrintMatrix(); ::system("PAUSE"); return 0;
コメントをかく