3

我一直在用 C++ 编写一些对文件进行操作的类。当我开始时,我让我的所有构造函数都接受一个std::string被解释为文件名的参数,因为这既快速又简单。

std::fstream任何类使用的唯一特定功能是.open(). 我认为,因为std::ofstreamandstd::ostringstream都派生自std::ostream并且我只使用's 函数,所以让每个构造函数适当地使用or参数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 可能会更好地处理指针,但对我来说,指向类的指针看起来很像动态分配的内存,如果它们是真的,我只想提出这些怀疑。解决这个问题的正确方法是什么?

4

4 回答 4

10

引用类型的成员(以及类型的成员const)必须在构造函数初始化列表中进行初始化:

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

原因是您需要立即初始化一个引用,然后再对它进行任何其他操作。您在原始代码中的内容是非法的,原因与非法的原因相同:

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

另一方面,初始化列表保证您的引用成员在进入构造函数的主体之前绑定到一个对象。

于 2013-05-15T22:27:37.560 回答
4

将您的代码更改为以下内容:

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

你所拥有的是一个分配,而不是初始化。您需要在成员初始化列表中初始化该成员。

当您点击构造函数的主体时{,所有类成员都已经存在于内存中。因此,在该行this->input = is;中,您试图分配is给一个已经存在的对象,但是,必须在 C++ 中初始化引用,因此出现错误消息:uninitialized reference member.

于 2013-05-15T22:27:18.050 回答
3

您应该在成员初始化列表中初始化您的参考成员。

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

C++ 引用不能赋值,因此必须在初始化列表中进行初始化。

于 2013-05-15T22:29:14.040 回答
2

改变你的构造这个这个

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

}

错误是

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

所以你必须初始化input

于 2013-05-15T22:29:21.220 回答