2016-10-27 5 views
0

これは私のプログラムです。私はタイプStudentのオブジェクトを作成し、次に学生にアイテムをチェックアウトさせる必要があります。そして、私はそのアイテムをチェックアウトさせるためにオーバーロードされた加算演算子を使用しています。オーバーロードされた加算演算子を使用するのが難しい

main.cppに:私がしようとすると、最小と簡素化、このプログラムを維持するために、ヘッダーファイル内のすべての私のクラスのdefintionsを定義し

#include <iostream> 
#include "Student.h" 

using namespace std; 

int main() { 

    Student s(54000, "JOHN", "DOE"); 

    cout << "main:" << endl << (s + "Frisbee") << endl << endl; 

    system("pause"); 

    return 0; 

} 

Student.h:

#ifndef STUDENT_H 
#define STUDENT_H 

#include <fstream> 
#include <string> 
#include <iostream> 

using namespace std; 

class Student { 

public: 

    string firstName; 
    string lastName; 
    int id; 
    int itemsCheckedOut; 
    int size; 
    string *array; 

    Student(int id = 0, string firstName = "", string lastName = "") { 
     Student::firstName = firstName; 
     Student::lastName = lastName; 
     Student::id = id; 
     itemsCheckedOut = 0; 
     size = 10; 
     array = new string[size]; 
    } 

    Student(const Student &other) { 
     itemsCheckedOut = other.itemsCheckedOut; 
     array = new string[itemsCheckedOut]; 
     for (int i = 0; i < itemsCheckedOut; i++) { 
      array[i] = other.array[i]; 
     } 
    } 

    ~Student() { 
     delete[] array; 
     array = NULL; 
    } 

    Student &operator=(const Student &rhs) { 
     if (this != &rhs) { 
      firstName = rhs.firstName; 
      lastName = rhs.lastName; 
      id = rhs.id; 
      itemsCheckedOut = rhs.itemsCheckedOut; 
      delete[] array; 
      array = new string[size]; 
      for (int i = 0; i < itemsCheckedOut; i++) { 
       array[i] = rhs.array[i]; 
      } 
     } 
     return *this; 
    } 

    void CheckOut(const string &item) { 
     array[itemsCheckedOut] = item; 
     itemsCheckedOut++; 
    } 

    friend ostream &operator<<(ostream &output, const Student &student) { 
     output << student.id << " " << student.firstName << " " << student.lastName << endl; 
     if (student.itemsCheckedOut != 0) { 
      output << student.itemsCheckedOut; 
      for (int i = 0; i < student.itemsCheckedOut; i++) { 
       output << " " << student.array[i] << endl; 
      } 
     } 
     else { 
      output << 0; 
     } 
     return output; 
    } 

    const Student operator+(const string &item) { 
     Student s; 
     s = *this; 
     s.CheckOut(item); 
     cout << "class:" << endl << s << endl << endl; 
     return s; 
    } 

}; 

#endif 

出力:あなたが見ることができるように

class: 
54000 JOHN DOE 
1 Frisbee 

main: 
-858993460 
1 Frisbee 

、メインから、そのは間違ったことを出力します。最初の名前と最後の名前の後に2つのスペースを続けてidを出力する代わりに、番号:-858993460を出力します。これはメモリリークの問題などがありますが、コピーコンストラクタ、オーバーロードされた代入演算子、およびデコンストラクタがすべて正しく定義されていることは間違いありませんが、それらを見ることができます。

私はここでかなり切望しているので、私はすべての助けに感謝します。ありがとう。

+0

修正しました。ありがとうございました。 – Jacob

答えて

0

(私はあなたがこのプロジェクトについての質問を投稿この最後の時間を言及した)これは、コピーコンストラクタを呼び出します。 デフォルトのコピーコンストラクタをオーバーライドするので、代入演算子の場合のように、すべてのデータコピーを手動で実行する必要があります。

+0

うわー、私はこれをキャッチしていないと信じることはできません。私は、コピーコンストラクタが動的配列や何かにしか使われていないと考えていたと思います。助けてくれてありがとう。 :) – Jacob

0

文字列*配列をstd :: vectorに置き換える必要があります。それはあなたのためのメモリ管理を処理し、あなたのコードをはるかに容易にし、現在使用している手動のメモリ管理よりもエラーが起こりにくくします。アイテムを追加するときに割り当てを行うことを心配している場合は、初期サイズを10に予約できます(このような小さなデータサイズでは問題にならないはずです)。

+0

これは学校での私の授業の1つの課題であり、ガイドラインではダイナミックな文字列配列を使用する必要があることが示されました。 – Jacob

+0

@Jacobあなたが言葉にうまくいて、教師がユーモア感覚を持っているならば、std :: vectorは内部的には動的配列を持っているので、間接的には使用しています:)。 – Lehu

+0

Lol、もしそれが簡単なのであれば...:Pしかし、実際には、ダイナミックな文字列配列で動作させる方法を理解したいと思います。なぜこれをやっているのか分かりません。 – Jacob

1

実際のoperator+が正しいように見えます。

  • がコピーコンストラクタがsizeid、または名前を設定しません。しかし、故障にそれを引き起こすあなたのコピーコンストラクタと代入演算子のバグがあります。
  • コピーコンストラクタは、のアイテムを割り当てます([itemsCheckedOut]ではなく)。
  • 代入演算子はsizeをコピーしません。
  • 割り当て演算子は、ディメンションが古いサイズの新しい配列を割り当てます。おそらく即時のバッファオーバーフローが発生します。
  • checkOut関数は、sizeを超える書き込みをチェックしません。このケースを検出して、チェックアウトを拒否するか、より多くの領域を割り当てる必要があります。
    Student(const Student &other) { 
        itemsCheckedOut = other.itemsCheckedOut; 
        array = new string[itemsCheckedOut]; 
        for (int i = 0; i < itemsCheckedOut; i++) { 
         array[i] = other.array[i]; 
        } 
    } 
    

    いますが、その本体内のすべての学生のフィールドをコピーするのを忘れ:
+0

助けてくれてありがとう@ M.M。そして確かに、CheckOutがサイズを超えて書き込もうとしていることを検出する機能を追加する必要があります。先端に感謝します。 :) – Jacob

関連する問題