-1

私はこれらのクラスを持っています:

class Base
{
  private:
    string name;
  public:
    void setName(string n);
    string getName();
    void toString();
}

そして、これから派生する 2 つのクラス:

class DerivedA : public Base
{
  private:
    int width;
  public:
    void setWidth(int w);
    int getWidth();

}

class DerivedB : public Base
{
  private:
    int height;
  public:
    void setHeight(int h);
    int getHeight();
}

今私の質問に。私のメインは次のようになります。

int main()
{        
  Base* b;    
  string line;
  ... file loading ...

  while(...)
  {
    s = cin.getline(file,10);        
    if(s == "w")
    {
      b = new DerivedA();        
    }
    else if(s == "h")
    {
      b = new DerivedB();
    }
    while(...)
    {
      b->toString();
    }
  }

return 0;
}

これにより、常にアプリが終了します。b->toString();スコープが異なるため、パーツが問題の原因である可能性があることがわかりました。とにかく、どうすればこれを行うことができますか?(コードの退屈で無関係な部分は省きました。)

4

1 に答える 1

2

Base仮想デストラクタが必要であり、オーバーライドする予定のすべての関数を宣言する必要がありますvirtual。さらに、main関数にはいくつかの変更が必要です。

int main()
{        
    Base* b = nullptr; // initialize your pointer    
    string line;
    // ... file loading ...

    while(std::getline(file, line)) // this should be your while loop for your file parsing
    {
        //s = cin.getline(file,10); // why???  you appear to be trying to pass your ifstream object into cin's istream::getline method ... this won't even compile!

        // I'm assuming s is a std::string, and you pull it out of the line variable at some point ...
        if(s == "w")
        {
           if (b != nullptr) // properly free your memory
           {
               delete b;
               b = nullptr;
           }
           b = new DerivedA();        
        }
        else if(s == "h")
        {
           if (b != nullptr) // properly free your memory
           {
               delete b;
               b = nullptr;
           }
            b = new DerivedB();
        }

        while(...)
        {
            if (b != nullptr) // make sure b is valid!
            {
                b->toString();
            }
        }
    }

    return 0;
}

これにより、常にアプリが終了します。b->toString(); が スコープが異なるため、部分が問題の原因である可能性があります。とにかく、どうすればこれを行うことができますか?

まず、あなたが投稿したものは(おそらく)コンパイルさえしません。 cin.getline標準入力から読み込もうとします。fileあなたのコメントは、あなたがファイルをロードしていることを示しているので、(それがstd::ifstreamインスタンスであると仮定して、存在しない cin.getline(file, 10)関数を呼び出そうとしています。ここでやりたいように見えます。さらに、標準から読み込もうとしている場合でも入力、すべきではありません。std::istream::getline(std::istream&, int)std::getlinestd::getline(std::cin, s)cin.getline(file, 10)

次に進むと、次の領域はメモリ リークです。これらは、1) 宣言時に初期化すること、および 2)メモリリークする前にb適切に修正することで簡単に修正できます。とにかくチェックするのでdelete、ヌルチェックは完全に必要というわけではありません(初期化されたb)が、ポイントを説明するためにそこに書きました:メモリを適切に管理する必要があります!deleteNULL

次に、if-else if-条件は何もしない可能性があります (つまり、b最悪の場合、またはNULLせいぜい初期化されません)。「s」/「h」以外の入力に対して何もしたくない場合は、それで問題ありませんが、次の項目を実行する必要があります (とにかく実行する必要があります)。

最後に、クラッシュの原因となっている可能性のある問題は、b使用する前に が有効かどうかを確認していないことです: b->toString();. が無効または null の場合b、未定義の動作を呼び出しています。プログラムがクラッシュしたり、祖母に電話したり、大統領にピザを注文したりするかもしれません...すべて有効なオプションであり、実際に意図したものではありません。

于 2013-10-30T21:04:42.860 に答える