-4

私は自由な時間に C++ の基礎を学び、本の演習に従っています。まず、行として 9 を入力し、列として 8 を入力すると、malloc 解放エラーが発生します。第二に、出力として 0 を取得します。入力内容がわかりません。3 のルールを強化できるので、プログラムを書きたいと思います。もちろん宿題ではありません。また、難しい質問で効率的な質問だと思います。質問に答えていただけると助かります。私はグーグルで検索したので、解決策について中途半端なことを見つけることができません。また、コピー コンストラクタ、代入演算子、およびデストラクタをチェックして、エラーの場所を教えてもらえますか?

コンストラクターでこの表示からのアイデアを使用して、double の 2 次元動的配列を実装するクラス TwoD を記述します。動的配列を指す double へのポインター型のプライベート メンバーと、MaxRows と MaxCols である 2 つの int (または unsigned int) 値が必要です。デフォルトの行と列の最大サイズを選択するデフォルトのコンストラクターと、プログラマーが行と列の最大サイズを設定できるパラメーター化されたコンストラクターを提供する必要があります。さらに、特定の行と列のエントリを設定できる void メンバー関数と、特定の行と列のエントリを double 型の値として返すメンバー関数を提供する必要があります。注意: [ ] をオーバーロードすることは (詳細に応じて) 困難または不可能であるため、2 次元配列に対して希望どおりに機能します。したがって、通常の関数表記法を使用してアクセサー関数とミューテーター関数を使用するだけです。+ 演算子をフレンド関数としてオーバーロードして、2 つの 2 次元配列を追加します。この関数は、左側のオペランド TwoD オブジェクトの i 行 j 列の要素と、右側のオペランド TwoD オブジェクトの i 行 j 列の要素の和を i 行 j 列の要素とする TwoD オブジェクトを返す必要があります。コピー コンストラクター、オーバーロードされた演算子 =、およびデストラクターを提供します。データを変更しないクラス メンバー関数を const メンバーとして宣言します。左側のオペランド TwoD オブジェクトの j 列要素と、右側のオペランド TwoD オブジェクトの i 行、j 列要素。コピー コンストラクター、オーバーロードされた演算子 =、およびデストラクターを提供します。データを変更しないクラス メンバー関数を const メンバーとして宣言します。左側のオペランド TwoD オブジェクトの j 列要素と、右側のオペランド TwoD オブジェクトの i 行、j 列要素。コピー コンストラクター、オーバーロードされた演算子 =、およびデストラクターを提供します。データを変更しないクラス メンバー関数を const メンバーとして宣言します。

私の努力

#include <iostream>
using std::cin;
using std::cout;
using std::endl;

class TwoD
{
public:
    TwoD();
    TwoD(int row, int column);
    void setRowCol();
    double getVal(int row, int column);
    friend const TwoD operator +(const TwoD& first, const TwoD& second);
    int getterRow() const;
    int getterCol() const;
    void setterRow(int row);
    void setterCol(int column);
    TwoD(const TwoD& object);
    TwoD& operator =(const TwoD& rightSide);
    void putArr() const;
    ~TwoD();
    static TwoD constructFromUserInput();
private:
    int MaxRows;
    int MaxCols;
    double **arr;
};

int main(int argc, char const *argv[])
{
    cout << "All size of TwoD object must be same\n\n";

    TwoD arr1 = TwoD::constructFromUserInput();
    TwoD arr2 = TwoD::constructFromUserInput();

    TwoD arr3;

    arr3 = arr1 + arr2;

    TwoD arr4(arr3);
    arr1.putArr();
    arr2.putArr();
    arr3.putArr();
    arr4.putArr();

    return 0;
}
void TwoD::setRowCol()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    MaxRows = r_user;
    MaxCols = c_user;

    TwoD(MaxRows,MaxCols);

}
TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
    arr = new double*[row];
    for (int i = 0; i < row; i++)
    {
        arr[i] = new double[column];
    }

    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> arr[i][j];
        }
    }
}
TwoD::TwoD()
: MaxRows(2), MaxCols(2)
{
    arr = new double*[2];
    for (int i = 0; i < 2; i++)
    {
        arr[i] = new double[2];
    }
}
double TwoD::getVal(int row, int column)
{
    return arr[row][column];
}
const TwoD operator +(const TwoD& first, const TwoD& second)
{
    TwoD sum;
    for (int i = 0; i < first.MaxRows; i++)
    {
        for (int j = 0; j < first.MaxCols; j++)
        {
            sum.arr[i][j] = first.arr[i][j] + second.arr[i][j];
        }
    }
    return sum;
}
TwoD::TwoD(const TwoD& object)
{
    MaxRows = object.MaxRows;
    MaxCols = object.MaxCols;

    arr = new double*[MaxRows];
    for (int i = 0; i < MaxRows; i++)
    {
        arr[i] = new double[MaxCols];
    }

    for ( int i = 0; i < MaxRows; i++ )
    {
        for ( int j = 0; j < MaxCols; j++ )
        {
            arr[i][j] = object.arr[i][j];
        }
    }
}
TwoD::~TwoD()
{
    for (int i = 0; i < MaxRows; i++)
        delete [] arr[i];
    delete [] arr;
}
TwoD& TwoD::operator =(const TwoD& rightSide)
{
    if (this == &rightSide)
    {
        return *this;
    }

    for (int i = 0; i < MaxRows; i++)
        delete [] arr[i];
    delete [] arr;

    arr = new double*[rightSide.MaxRows];
    for (int i = 0; i < rightSide.MaxRows; i++)
    {
        arr[i] = new double[rightSide.MaxCols];
    }

    MaxRows = rightSide.MaxRows;
    MaxCols = rightSide.MaxCols;

    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            arr[i][j] = rightSide.arr[i][j];
        }
    }
    return *this;
}
void TwoD::putArr() const
{
    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            cout << arr[i][j] << " ";
        }
        cout << endl;
    }
}
int TwoD::getterRow() const
{
    return MaxRows;
}
int TwoD::getterCol() const
{
    return MaxCols;
}
void TwoD::setterRow(int row)
{
    MaxRows = row;
}
void TwoD::setterCol(int column)
{
    MaxCols = column;
}
TwoD TwoD::constructFromUserInput()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    // Construct an object.
    TwoD obj(r_user, c_user);

    // Return the object
    return obj;
}
4

2 に答える 2

2
  1. コピー コンストラクターは配列を作成しますが、内容をコピーすることはありません。コピー代入演算子はこれを正しく行います。さらに言えば、複製されnew[]たループがたくさんあり、いくつかのdelete[]ループがあり、2 つのコピー ループが必要です。これらを関数に分解すると、それらを一度正しく取得するだけで済みます。

  2. sumデフォルトサイズのオブジェクトを作成し、おそらく行と列の両方の次元をオーバーランします。通常の (簡単で正しい) 実装は、左側の引数のローカル コピーを作成し (上で修正したコピー ctor を使用して)、 に転送することoperator+=です。その演算子は、正しく取得する方がはるかに簡単です。

  3. これらの行列を出力する方法があります。やれ!どこでもやれ!これにより、どの段階で問題が発生したかを簡単に確認できます。

  4. この本はあまり良く聞こえません。明らかな理由もなく、悪い練習を教えています(演算子+トリックは標準です。unique_ptr使用できない場合は使用する必要がありますvectorなど)。


編集: チャット セッションになる危険性があるため、ここでいくつかのコメントに返信します。これ以上時間を費やしたくありません。

  • コピーコンストラクターを修正しましたか?

    これは、コードのテストとデバッグの方法を理解する良い機会です。print ステートメントを追加し、デバッガーを使用し、テストできる関数に分割してから、それらのテストを記述します。

  • delete[]2 つのループと 2 つのコピー ループがあることを意味します

    コード内のループを探します。3 つのループが を呼び出していることがわかりますがnew[]、すべて基本的に同じことを行っています。2 つのループが呼び出されていることがわかりますdelete[]。1 つはデストラクタで、もう 1 つはコピー代入演算子です。独自のコードでforキーワードを検索するだけです。

  • マトリックスを印刷する方法が本当にわかりません

    だからどこTwoD::putArrから来たの?確かに、その名前ostream& operator<<(ostream&, TwoD const &)が適切ですが、あなたが書いたので、それを使用することもできます。

  • デストラクタを main() に入れることができません

    main が終了したときに呼び出されるデストラクタを停止することはできません。その場合、オブジェクトは範囲外になります。デストラクタにブレークポイントを設定するだけで呼び出されます。

  • arr は非公開なので、どうすればテストできますか?

    あなたはまだデバッガーでそれを見ることができます、あなたはまだ内容を印刷することができます(上記のように)、あなたはまだgetValユニットテストから呼び出すことができます、あなたはpublicあなたの問題を理解するまでそれを作ることができます

于 2015-09-02T17:05:26.047 に答える
0

コードの問題:

void TwoD::setRowCol()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    MaxRows = r_user;
    MaxCols = c_user;

    ///
    /// This constructs a new TwoD object but does not change
    /// object on which the function was invoked.
    ///
    TwoD(MaxRows,MaxCols);    
}

問題を解決する方法:

メンバーデータを更新する

void TwoD::setRowCol()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    // Delete the current memory
    for (int i = 0; i < MaxRows; i++)
    {
       delete [] arr[i];
    }

    delete [] arr;

    MaxRows = r_user;
    MaxCols = c_user;

    // Allocate new memory.
    arr = new double*[MaxRows];
    for (int i = 0; i < MaxRows; i++)
    {
       arr[i] = new double[MaxCols];
    }

    // Now read the data.
    for (int i = 0; i < MaxRows; i++)
    {
        for (int j = 0; j < MaxCols; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> arr[i][j];
        }
    }
}

まったく新しいオブジェクトを返す関数を作成する

この方法をお勧めします。

まず、ユーザー入力からデータを読み取るコードが含まれないように、行と列を受け取るコンストラクターを更新します。

TwoD::TwoD(int row, int column)
: MaxRows(row), MaxCols(column)
{
    arr = new double*[row];
    for (int i = 0; i < row; i++)
    {
        arr[i] = new double[column];
    }
}

次に、staticメンバー関数を追加して、ユーザー入力からオブジェクトを構築します。

static TwoD constructFromUserInput();

そしてそれを次のように実装します:

TwoD TwoD::constructFromUserInput()
{
    int r_user;
    int c_user;
    cout << "Enter num of rows => ";
    cin  >> r_user;
    cout << "Enter num of columns => ";
    cin  >> c_user;

    // Construct an object.
    TwoD obj(r_user, c_user);

    // Now read the data.
    for (int i = 0; i < r_user; i++)
    {
        for (int j = 0; j < c_user; j++)
        {
            cout << "Enter for " << i << j << "=> ";
            cin  >> obj.arr[i][j];
        }
    }

    // Return the object
    return obj;
}

3 番目に、 の新しい関数を使用しmainます。

int main(int argc, char const *argv[])
{
   cout << "All size of TwoD object must be same\n\n";

   TwoD arr1 = TwoD::constructFromUserInput();
   TwoD arr2 = TwoD::constructFromUserInput();

   TwoD arr3;

   arr3 = arr1 + arr2;
   arr1.putArr();
   arr2.putArr();
   arr3.putArr();

   return 0;
}
于 2015-09-02T18:16:10.197 に答える