2011-01-24 32 views
3

繼承我可以從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(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; 
} 

我希望它讀取整個文件,但它讀取只是一個符號(這是不是第一次給定文件的符號)...

+0

good()!!這是做什麼的? – DumbCoder

+1

'ifstream(fname,mode)'應該被移動到一個初始化列表。您應該在嘗試讀取數據和使用它之間進行一些錯誤檢查,而不是僅在該進程的迭代之間進行。 –

+0

這可能有所幫助:http://stackoverflow.com/questions/772355/how-to-inherit-from-stdostream – Skurmedel

回答

0

您缺少對基礎構造函數的調用。我想你的意思是這樣的:

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

} 

,而不是這樣的:

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

現在你會閱讀一些未初始化內存的內容。第二個(當前)代碼只是在堆棧上創建一個新的ifstream實例,並立即銷燬它。

+0

在封閉流上嘗試讀取不會給您未初始化的內存;根據ISO/IEC 14882:1998(E)27.6.1.3.20'std :: getline(char_type *,streamsize)'將永遠終止其結果。不幸的是,代碼在讀取後沒有測試failbit錯誤代碼,所以它沒有意識到它得到了一個虛假的空字符串。 – bdonlan

+0

@bdonlan:感謝您的澄清。 –

6

不要繼承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

我沒有看到一個問題,你的提取功能,但我不明白,從ifstream的派生點。

從一個類派生的目的是覆蓋它的虛擬方法,以便當有人將一個istream &或ifstream &放入一個函數(通常是operator >>)時,您的覆蓋被調用。

與STL集合不同,流確實使用層次結構和v-表,但新手通常會錯誤地理解概念。

例如,如果您想更改它使用的緩衝區類型,您將從basic_streambuf派生並使用連接了您的streambuf的簡單istream或ostream對象。

更改打印或讀取對象的方式不是通過從iostream或streambuf派生新類而可以實現的,也不能擴展iomanips,您必須在流式傳輸對象周圍使用包裝類。