2016-02-04 10 views
0

фона:не может перегрузить оператор ofstream из-за - не может связываться с величиной несвязанной типа (глава Страуструп C++ 10)

Я работаю свой путь, хотя гр книги Страуструпа ++. Я нахожусь в главе 10, посвященной упражнениям и сталкиваюсь с проблемой. Теперь, насколько я могу судить, я не строго следую книге, основываясь на том, как я видел, как другие отвечают на вопросы. Я думаю, Im сразу после немного большего понимания того, как реализовать код.

Моя общая цель - иметь функцию записи, а не иметь ее в main().

Целью следующей функции является возвращение потока.

ofstream& c_data_file() 
{ 
    string oname = "mydata.txt"; 
    ofstream ost {oname}; 
    if (!ost) { 
     string error = "cannot open " + oname; 
     throw runtime_error(error); 
    } 
    return ost; 
} 

Этот код приходит с предупреждением от компилятора, и я в том числе, так как она может быть связана с проблемой. Предупреждение:

Reference to stack memory associated with local variable 'ost' returned

ostream& operator<<(ostream& os, const Point& p) 
{ 
    return os << "(" << p.x <<"," <<p.y <<")"; 
} 

ofstream& operator<<(ofstream& ost, const Point& p) 
{ 
    return ost << "(" << p.x <<"," <<p.y <<")"; 
} 

ostream отлично работает (я использую этот поток еще где). Ofstream не работает, возвращая ошибку:

Non-const lvalue reference to type 'ofstream' (aka 'basic_ofstream') cannot bind to a value of unrelated type 'basic_ostream >'

Ниже приводится остальная часть соответствующего кода:

int main() { 

    vector<Point> original_points; 
ofstream& ost = c_data_file(); 
    for (int i = 0; i<original_points.size(); i++) { 
     ost << original_points[i] << "\n"; 
    } 
    ost.close(); 
} 

Я смотрел онлайн весь день, следующий вопрос кажется шкаф:

overloaded operator << on ofstream concatenation problems

Однако, я считаю, что это трудно понять ответ и от того, что я понимаю, это не решает мою проблему.

Благодарим вас за чтение и за любую помощь, которую вы можете дать.

Здесь я включаю следующие изменения, а также свой ответ на iksemyonov с надеждой четко выразить проблему для всех. Редактирование 1: предупреждение было разрешено после рекомендации TBBle. Основная проблема по-прежнему стоит, поскольку ссылка указывает, и iksemyonov предлагает мне использовать ostream вместо потока. Это проблематично. Ostream (по книге) используется для отправки данных в cout, что я делаю (код не присутствует). Я также хочу отправить те же данные в файл (в идеале, как предлагает книга через thestream).

Редактировать 2: после выполнения ссылок и предложений iksemyonov. Несколько комментариев ниже помогли мне выполнить предложения. Так что спасибо всем, кто прокомментировал это.

+0

Первое предупреждение - это то, что вы действительно возвращаете ссылку на временный 'ost', который создается в стеке. Это может привести к сбою, поскольку после того, как функция «ost' выходит за пределы области действия после возвращения функции, она * не гарантируется * существует, поскольку она * может * рано или поздно быть удалена. Таким образом, предупреждение. – iksemyonov

+1

Вы возвращаете ссылку на локальную переменную. Это ** неопределенное поведение ** – PaulMcKenzie

ответ

1

Основываясь на ссылке, предоставленной О.П.,

overloaded operator << on ofstream concatenation problems

кроме исправление , возвращающее ссылку на временная ошибка, исправление изменить

ofstream& operator<<(ofstream& ost, const Point& p) 
{ 
    return ost << "(" << p.x <<"," <<p.y <<")"; 
} 

в

ostream& operator<<(ostream& ost, const Point& p) 
{ 
    return ost << "(" << p.x <<"," <<p.y <<")"; 
} 

который компилирует просто отлично. Как поясняется в ответ в ссылке, причиной возникновения ошибки является то, что ost << "(" возвращает объект типа ostream, а дальнейшие вызовы operator<<, таким образом, терпят неудачу из-за несовместимости, сообщаемой компилятором.

На стороне примечания, это не хороший стиль, чтобы не возвращать код выхода из основного, как в return 0.

+0

Хорошо, моя проблема заключается в том, что Я уже использую ostream для отправки данных в cout. Могу ли я также использовать его в то же время для отправки данных в файл (или ost)? Я просто попытался удалить поток и сохранить только ostream и создал ошибку компоновщика и другую ошибку –

+0

Что такое «еще одна ошибка»? Ответ правильный: «поток» - это «поток», поэтому предоставление только одного «потока» и оператора << (ofstream &, const Point &) »должно выполнять оба варианта использования. – TBBle

+0

http: //coliru.stacked-crooke d.com/a/85710943cab5126e это прекрасно строит – iksemyonov

0

ofstream& c_data_file() возвращает ссылку (&) к ofstream ost;, которая больше не существует (ofstream ost; является локальным объектом и собирается быть уничтожен, когда он выходит из области видимости)

так, что вы могли бы сделать вместо того, чтобы это изменить вашу функцию ofstream c_data_file(), и таким образом вы больше не будете возвращать временный объект.

1

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

Таким образом, вы должны вернуть объект ofstream.

You can't copy streams, так что это должно быть движение. К счастью, в этом случае это будет автоматически. (Предполагая, что C++ 11. Если нет, вам необходимо перестроить свой код).

И если вы находитесь на gcc перед gcc 5, you can't move streams due to a bug.

Так самое простое изменение в вашей функции:

ofstream c_data_file() 
{ 
    string oname = "mydata.txt"; 
    ofstream ost {oname}; 
    if (!ost) { 
     string error = "cannot open " + oname; 
     throw runtime_error(error); 
    } 
    return ost; 
} 

и вызывающий становится

ofstream ost = c_data_file(); 
+0

TBBle, ошибка, похоже, действительно описана OP в его ссылке. А именно, что 'os <<" ("' возвращает 'ostream', а не' ofstream'. Не могли бы вы объяснить детали, почему это происходит? Это строка, где возникает ошибка, проверяется с помощью компилятора. – iksemyonov

+0

Собственно, d) не замечал, что это была ошибка, я смотрел на предупреждение. Ваш ответ выше относится к актуальной проблеме. – TBBle

+0

Спасибо TBBle, это зафиксировало предупреждение, но не решило основной проблемы. –