2013-05-15 32 views
3

我一直在用C++編寫一些操作文件的類。當我開始時,我讓所有的構造函數接受一個std::string參數,這個參數被解釋爲一個文件名,因爲這很快且容易。C++多態與引用

唯一功能std::fstream任何類使用的是.open()。我認爲,因爲std::ofstreamstd::ostringstream都來自std::ostream,我只使用std::ostream的函數,所以最好讓每個構造函數適當地採用std::ostreamstd::istream參數,而不是將類綁定到文件。

爲什麼多態性很有用的一本很好的教科書示例。雖然GCC很不高興。這是我的代碼的簡化:

#include <iostream> 
#include <fstream> 

class Foo { 
     public: 
       Foo(std::istream&); 
       std::istream& input; 
}; 

Foo::Foo(std::istream& is) { 
     this->input = is; 
} 

int main() { 
     std::ifstream is("test.txt"); 
     Foo foo(is); 
} 

,當與g++ test.cpp編譯,產生錯誤的以下豐富多彩的品種:

test.cpp: In constructor ‘Foo::Foo(std::istream&)’: 
test.cpp:10:1: error: uninitialized reference member ‘Foo::input’ [-fpermissive] 
In file included from /usr/include/c++/4.7/ios:43:0, 
       from /usr/include/c++/4.7/ostream:40, 
       from /usr/include/c++/4.7/iostream:40, 
       from test.cpp:1: 
/usr/include/c++/4.7/bits/ios_base.h: In member function ‘std::basic_ios<char>& std::basic_ios<char>::operator=(const std::basic_ios<char>&)’: 
/usr/include/c++/4.7/bits/ios_base.h:791:5: error: ‘std::ios_base& std::ios_base::operator=(const std::ios_base&)’ is private 
In file included from /usr/include/c++/4.7/ios:45:0, 
       from /usr/include/c++/4.7/ostream:40, 
       from /usr/include/c++/4.7/iostream:40, 
       from test.cpp:1: 
/usr/include/c++/4.7/bits/basic_ios.h:64:11: error: within this context 
In file included from /usr/include/c++/4.7/iostream:41:0, 
       from test.cpp:1: 
/usr/include/c++/4.7/istream: In member function ‘std::basic_istream<char>& std::basic_istream<char>::operator=(const std::basic_istream<char>&)’: 
/usr/include/c++/4.7/istream:56:11: note: synthesized method ‘std::basic_ios<char>& std::basic_ios<char>::operator=(const std::basic_ios<char>&)’ first required here 
test.cpp: In constructor ‘Foo::Foo(std::istream&)’: 
test.cpp:11:16: note: synthesized method ‘std::basic_istream<char>& std::basic_istream<char>::operator=(const std::basic_istream<char>&)’ first required here 

我有麻煩通過所有的模板參數篩選,但它看起來像它不喜歡this->input = is;。對於每個類都能夠作爲成員訪問流是很重要的,因爲各種不同的成員函數都必須能夠看到它。我認爲GCC可能對指針更好,但對我來說,指向類的指針看起來像動態分配的內存,我只想提出這些懷疑,如果他們是真的。什麼是正確的方式去做這件事?

回答

10

成員(以及一個const類型的成員)必須在constructor initialization list進行初始化:

Foo::Foo(std::istream& is) : input(is) 
//       ^^^^^^^^^^^ 
{ 
} 

的原因是,你馬上需要初始化參考,在此之前其他任何東西。你在你原來的代碼是什麼出於同樣的原因,爲什麼這是非法違法:

int y = 42; 
int& x; // ERROR! 
x = y; 

初始化列表,而另一方面,保證您的參考件的身體之前綁定到一個對象構造函數被輸入。

+0

很好的鏈接和很好的解釋,正是我一直在尋找。 – Monchoman45

+0

@ Monchoman45:很高興幫助;) –

4

你的代碼更改爲以下:

Foo::Foo(std::istream& is) : input(is) { 
} 

你有什麼是分配,不初始化。您需要在成員初始化列表中初始化成員。

當您碰到構造函數{的主體時,所有的類成員都已經存在於內存中。因此,在行this->input = is;中,您試圖將is分配給已經存在的對象,但是,必須使用C++初始化引用,因此會出現錯誤消息:uninitialized reference member。引用類型的

3

您應該在成員初始化列表中初始化您的引用成員。

Foo::Foo(std::istream& is): input(is) { 
} 

C++引用不能分配,因此它必須在初始化列表中初始化。

2

改變你的構造這本

Foo::Foo(std::istream& is):input(is) { 

} 

誤差

error: uninitialized reference member ‘Foo::input’ [-fpermissive] 

,所以你必須初始化input