Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从ifstream继承_C++_Inheritance_Ifstream - Fatal编程技术网

C++ 从ifstream继承

C++ 从ifstream继承,c++,inheritance,ifstream,C++,Inheritance,Ifstream,我是否可以从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

我是否可以从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;
}
#包括
使用名称空间std;
常量字符串用法\u str=“用法:提取”;
类文件:公共ifstream
{
公众:
显式文件(const char*fname,openmode=in);
孔隙提取物(ostream&o);
};
文件::文件(常量字符*fname,openmode模式)
{
ifstream(fname,mode);
}
void File::extract(ostream&o)
{
char ch;
char-buf[512];
int i=0;
while(good()){
getline(buf,sizeof(buf));

o您缺少对基本构造函数的调用。我想您的意思是:

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

}
与此相反:

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

现在您可能正在读取一些未初始化内存的内容代码只是在堆栈上创建一个新的ifstream实例并立即将其销毁。

不要从ifstream继承。如果需要更改输入流的行为,请从中继承,然后围绕它构造一个实例。如果只想添加帮助程序,请将其设为全局,以便可以在任何istream上使用它们

也就是说,您的bug在文件构造函数中:

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

}
这将构造一个(未命名)ifstream,然后立即将其关闭。要调用超类构造函数:

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

}

我认为您的提取函数没有问题,但我不明白从ifstream派生的意义

从类派生的目的是重写其虚拟方法,以便当有人将istream&或ifstream&传递给函数(通常是运算符>>)时,调用重写

与STL集合不同,streams确实使用层次结构和v形表,但新手通常会误解这个概念

例如,如果您想更改它使用的缓冲区类型,您可以从basic_streambuf派生并使用一个简单的istream或ostream对象,并附加streambuf


通过从iostream或streambuf派生一个新类,您无法更改对象的打印或读取方式,也无法扩展iomanips,您必须在正在流式处理的对象周围使用包装类。

good()!!这有什么作用?
ifstream(fname,mode)
应该移到初始化器列表中。您应该在尝试读取数据和使用数据之间进行一些错误检查,而不仅仅是在该过程的迭代之间。这可能会有所帮助:在您的位置上,我更喜欢聚合而不是继承。在这种情况下,您仍然可以使用这些方法,而不必担心ifstream实际会发生什么oes.根据ISO/IEC 14882:1998(E)27.6.1.3.20
std::getline(字符类型*,流大小),尝试在封闭流上读取不会给您未初始化的内存
将始终为空并终止其结果。不幸的是,读取后代码没有测试failbit错误代码,因此它没有意识到它得到的是一个伪造的空字符串。@bdonlan:谢谢您的澄清。