4

ifstream から継承して、次のように派生クラスからファイルを読み取ることはできますか?

#include <iostream>

using namespace std;

const string usage_str = "Usage: extract <file>";

class File: public ifstream
{
public:
    explicit File(const char *fname, openmode mode = in);
    void extract(ostream& o);
};

File::File(const char *fname, openmode mode)
{
    ifstream(fname, mode);
}

void File::extract(ostream& o)
{
    char ch;
    char buf[512];
    int i = 0;

    while (good()) {
        getline(buf, sizeof(buf));
        o<<buf;
        i++;
    }   
    cout<<"Done "<<i<<" times"<<endl;
}

void msg_exit(ostream& o, const string& msg, int exit_code)
{
    o<<msg<<endl;
    exit(exit_code);
}

int do_extract(int argc, char *argv[])
{
    cout<<"Opening "<<argv[1]<<endl;
    File f(argv[1]);
    if (! f)
        msg_exit(cerr, usage_str, 1);
    f.extract(cout);
    return 0;
}

int main(int argc, char *argv[])
{
    if (argc < 2)
        msg_exit(cout, usage_str, 0);

    do_extract(argc, argv);
    return 0;
}

ファイル全体を読み取ることを期待していますが、1つのシンボルのみを読み取ります(これは、指定されたファイルの最初のシンボルではありません)...

4

3 に答える 3

7

ifstream から継承しないでください。入力ストリームの動作を変更する必要がある場合は、streambufistreamから継承し、その周りにを構築します。ヘルパーを追加するだけの場合は、それらをグローバルにして、任意の istream で使用できるようにします。

つまり、あなたのバグは File コンストラクターにあります。

File::File(const char *fname, openmode mode)
{
    ifstream(fname, mode);
}

これは (名前のない) ifstream を構築し、すぐに閉じます。スーパークラス コンストラクターを呼び出したい場合:

File::File(const char *fname, openmode mode)
  : ifstream(fname, mode);
{

}
于 2011-01-24T09:49:28.267 に答える
1

抽出関数に問題はありませんが、ifstream から派生させる意味がわかりません。

クラスから派生させる目的は、その仮想メソッドをオーバーライドして、誰かが istream& または ifstream& を関数 (通常は operator>>) に渡すと、オーバーライドが呼び出されるようにすることです。

STL コレクションとは異なり、ストリームは階層と v テーブルを使用しますが、初心者は通常、概念を誤解します。

たとえば、使用するバッファ タイプを変更する場合は、basic_streambuf から派生させて、streambuf をアタッチした単純な istream または ostream オブジェクトを使用します。

オブジェクトの出力方法や読み取り方法を変更することは、iostream や streambuf から新しいクラスを派生させることによってできることではありません。また、iomanips を拡張することもできません。ストリーミングしているオブジェクトの周りにラッパー クラスを使用する必要があります。

于 2011-01-24T09:54:43.070 に答える
0

基本コンストラクターへの呼び出しがありません。私はあなたがこれを意味すると思います:

File::File(const char *fname, openmode mode) : ifstream(fname, mode)
{

}

これの代わりに:

File::File(const char *fname, openmode mode)
{
    ifstream(fname, mode);
}

現在、おそらく初期化されていないメモリの内容を読み取っています。2 番目の (現在の) コードは、スタック上に ifstream の新しいインスタンスを作成し、すぐに破棄します。

于 2011-01-24T09:47:20.817 に答える