Наследование от ifstream - PullRequest
       8

Наследование от ifstream

4 голосов
/ 24 января 2011

Могу ли я наследовать от 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;
}

Я ожидаю, что он прочитает весь файл, но он читает только один символ (который не является первым символом данного файла) ...

Ответы [ 3 ]

7 голосов
/ 24 января 2011

Не наследуй от ifstream.Если вам нужно изменить поведение входного потока, наследовать от streambuf , то создайте вокруг него istream.Если вы просто хотите добавить помощников, сделайте их глобальными, чтобы вы могли использовать их на ЛЮБОМ istream.

Тем не менее, ваша ошибка в конструкторе файлов:

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

Это создает (безымянный) ifstream, то сразу его закрывает.Вы хотите вызвать конструктор суперкласса:

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

}
1 голос
/ 24 января 2011

Я не вижу проблемы с вашей функцией извлечения, но у меня нет смысла выводить из ifstream.

Цель наследования от класса состоит в том, чтобы переопределить его виртуальные методы так, чтобы, когда кто-то передаетistream & или ifstream & в функцию (обычно оператор >>), которую вызывается ваше переопределение.

В отличие от коллекций STL, потоки используют иерархию и v-таблицы, но новички, как правило, неправильно понимают эту концепцию.

Например, если вы хотите изменить тип буфера, который он использует, вы бы унаследовали от basic_streambuf и использовали бы простой объект istream или ostream с вашим приложением streambuf. * ​​1007 *

Изменение способа печати или чтения объектов не является чем-товы можете сделать это путем извлечения нового класса из iostream или streambuf, и при этом вы не можете расширять iomanips, вы должны использовать классы-обертки вокруг потоковых объектов.

0 голосов
/ 24 января 2011

Вы пропустили вызов базового конструктора.Я думаю, что вы имеете в виду это:

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

}

вместо этого:

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

Сейчас вы, вероятно, читаете содержимое некоторой неинициализированной памяти.Второй (текущий) код просто создает новый экземпляр ifstream в стеке и сразу его уничтожает.

...