2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
1

Класс содержащий объект типа ofstream - не компилится!

28.07.2012, 14:03. Показов 9701. Ответов 21
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте! Помогите пожалуйста!=)

есть код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <fstream>
 
    class Monstr
    {
        private:
            std::ofstream out;
        public:
            Monstr() : out("test", std::ios::app | std::ios::out){}
            ~Monstr();
    };
 
 
int main(void)
{
    Monstr Y;
    Monstr X(Y);
    system("pause");
    return 0;
}
есть ошибка:

1>c:\program files\microsoft visual studio 10.0\vc\include\ostream(604): error C2249: std::basic_ios<_Elem,_Traits>::operator =: нет доступного пути к private член, объявленному в виртуальном базовом классе "std::basic_ios<_Elem,_Traits>"
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> c:\program files\microsoft visual studio 10.0\vc\include\ios(177): см. объявление "std::basic_ios<_Elem,_Traits>::operator ="
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1> Сообщение диагностики возникло в созданной компилятором функции "std::basic_ostream<_Elem,_Traits> &std::basic_ostream<_Elem,_Traits>::operator =(const std::basic_ostream<_Elem,_Traits> &)"
1> with
1> [
1> _Elem=char,
1> _Traits=std::char_traits<char>
1> ]
1>


Почему?

Добавлено через 5 минут
И если размещают объекты класса [i/o]fstream в классе, то как? Или что-то в конструкторе копирования для этого делают обычно? И еще, как вернуть имя файла, на который ссылается объект класса [i/o]fstream. Т.е.

ofstream out1("test");
ofstream out2(out.вернуть_имя_файла);?
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.07.2012, 14:03
Ответы с готовыми решениями:

Есть объект типа T, но если вместо него подставить вызов функции, возвращающей T, код не компилится, почему?
Есть объект типа vector&lt;int&gt;, но если вместо него подставить вызов функции, возвращающей...

Класс, содержащий объект своего класса
Если класс содержит объект своего класса. Почему при создании объекта такого класса не создается...

Объявить класс содержащий 1 переменную А закрытого типа.
объявить класс содержащий 1 переменную А закрытого типа. И функцию которая считывает переменную...

Сериализовать класс, содержащий экземпляры других классов и листы с объектами типа object
Не получается сериализовать класс, содержащих экземпляры других классов и листы с объектами типа...

21
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
28.07.2012, 14:07 2
Создается конструктор копирования по умолчанию, в котором идет по элементное присваивание. А объекты типа std::ofstream нельзя присваивать через оператор =. Определите явный конструктор копии, и в нем производите действия.
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
28.07.2012, 15:37  [ТС] 3
А что в конструкторе копирования написать, чтобы данное поле во всех экземплярах класса ссылалось на один и тот же файл?
0
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
28.07.2012, 17:43 4
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
конструкторе копирования написать
ИМХО Лучше определить метод(ы) для работы
с файлом

Объекты кл. ofstream, ifstream создавать в main

и передавать в эти методы

Примерчик
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <fstream>
 
    class Monstr
    {
        private:
 
           int age;
 
        public:
 
            Monstr() : age ( 0 ){}
            Monstr( int age_ ) : age ( age_ ){}
            ~Monstr(){};
            void fileWork ( std::ofstream & f );
 
    };
 
     void Monstr::fileWork ( std::ofstream & f )
          {
                  f << age << std::endl;
          }
 
 
int main(void)
{
 
   Monstr obj ( 33 );
   Monstr obj2 ( 56 );
 
   std::ofstream out;
   out.open ( "C:\\test.txt"  );
 
   obj.fileWork ( out );
   obj2.fileWork ( out );
 
   out.close();
 
    system("pause");
    return 0;
}
в файле получим
Код
33
56
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
конструкторе копирования написать
Alberto_Timakov, загляните в ios_base.h и увидите что
конструктор копии и оператор присваивания для класса IOS_BASE
находятся в разделе private

потому
Цитата Сообщение от Toshkarik Посмотреть сообщение
А объекты типа std::ofstream нельзя присваивать через оператор =.
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
28.07.2012, 20:47 5
Думаю сама идея объявления потока в классе как члена- не хорошая
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 02:08  [ТС] 6
Цитата Сообщение от MrCold Посмотреть сообщение
Объекты кл. ofstream, ifstream создавать в main
и передавать в эти методы
Спасибо! верно! Но что, если я хочу, к примеру, какую-нибудь отладочную печать в файл в деструкторе написать? Ему ведь параметров передавать нельзя...Ну или вообще может есть случаи, положим исключительные, когда прям надо чтобы поле было типа fstream?

Цитата Сообщение от Avazart Посмотреть сообщение
Думаю сама идея объявления потока в классе как члена- не хорошая
А почему?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2012, 08:36 7
По тому что лучше локализовать существование потока внутри метода, там же обрабатывать ошибки в/в.
0
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
29.07.2012, 09:57 8
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
может есть случаи, положим исключительные, когда прям надо чтобы поле было типа fstream?
Пишем значение переменной age в файл
затем выводим

для каждого объекта Monstr свой файл
( конечно можно и в один файл
записи добавлять )

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <iostream>
#include <fstream>
 
    class Monstr
    {
        private:
 
           int age;
           char *fname;
           std::ofstream out;
           std::ifstream in;
 
    private:
 
        Monstr& operator=( const Monstr& src );
        Monstr( const Monstr& src );
 
    public:
 
         void 
               writeFile() 
           {
                out.open ( fname );
                 if ( ! out )
                 {
                     std::cerr << "Error in opening file for writing.";
                       exit ( -1 );
                 }
            
               out << age << std::endl;
               out.close();
           }
 
          void 
               readFile()
           {
                 in.open ( fname );
                 if ( ! in )
                 {
                     std::cerr << "Error in opening file for reading.";
                       exit ( -1 );
                 }
               int val = 0;
                        
                   in >> val ;
                   std::cout << val << std::endl; 
                   in.close();
           }
 
        public:
 
            Monstr( const char *fname_ = "C:\\file1.txt" , int age_ = 23 ) :
              age ( age_)
            {
                fname = new char [ strlen ( fname_) + 1 ];
                strcpy( fname, fname_);
            }
 
            ~Monstr()
            {
               delete[] fname;
            }    
 
    };
 
int main(void)
{
   Monstr obj ( "C:\\file1.txt" );
   Monstr obj2 ( "C:\\file2.txt" , 53 );
 
   obj.writeFile();
   obj.readFile();
 
   obj2.writeFile();
   obj2.readFile();
 
    system("pause");
    return 0;
}
Вывод в консоль :
Код
23
53
В файлах :

file1: 23
file2: 53
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 10:22  [ТС] 9
Вы написали:
Цитата Сообщение от MrCold Посмотреть сообщение
private:
Monstr& operator=( const Monstr& src );
Monstr( const Monstr& src );
Во-первых, почему именно private?
Во-вторых, где определение?)

Добавлено через 9 минут
Я не фига не понял, как оно работает? Ведь определений даже нету? И что это из себя представляет расскажите пожалуйста...
0
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
29.07.2012, 10:24 10
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
Во-первых, почему именно private?
Что бы запретить присваивание ;
C++
1
2
3
Monstr obj; 
Monstr obj2 = obj; < ------ запрет 
Monstr obj3 (obj); < ------ запрет
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
Во-вторых, где определение?)
Определение уже не понадобится т.к. конструктор копии
и оператор присваивания все равно
недоступны ( private )

запрещаем присваивание, копирование
объектов потому-что
C++
1
std::ofstream out = std::ofstream out;  <  --------------- НЕЛЬЗЯ!!!!!
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 10:40  [ТС] 11
Цитата Сообщение от MrCold Посмотреть сообщение
Что бы запретить присваивание ;
Познавательно, спасибо!

Так, енто понятно, ну, а если все таки объекты у меня в программе копируются...то что тогда...может можно как-нибудь с указателями?

Я просто пробовал писать вот так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <fstream>
 
    class Monstr
    {
        private:
            std::ofstream * out;
        public:
            Monstr(){out = new std::ofstream ("test", std::ios::app | std::ios::out);}
            Monstr(const Monstr &);
            ~Monstr(){*out << "destructor" << std::endl; *out.close(); }
    };
 
    Monstr::Monstr(const Monstr & monstr)
    {
        out = monstr.out;
        *out << "constructor_copy" << std::endl;
    }
 
 
int main(void)
{
    Monstr Y;
    Monstr X(Y);
    system("pause");
    return 0;
}
- Работает, но без delete out в деструкторе ~Monstr(). С delete естественно возникает ошибка из-за повторного освобождения одной и той же области...Без delete это бред, я понимаю, но может можно еще как-то????
0
873 / 771 / 173
Регистрация: 11.01.2012
Сообщений: 1,942
29.07.2012, 10:58 12
C++
1
2
private:
            std::ofstream  out;
Зачем вообще ofstream, ifstream
выносить из методов
работайте внутри методов

открыли - записали- закрыли
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
   void    writeFile() 
        {
          std::ofstream  out;
       out.open ( "file.txt" , std::ios::app );
                if ( ! out )
                {
                     std::cerr << "Error in opening file.";
                      exit ( -1 );
                }
         
              out << age << std::endl;
               out.close();
         }
Это последнее что предложу
1
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2012, 11:44 13
C++
1
2
3
4
5
6
7
bool Monstr::writeFile(std::string filename) 
  {
    std::ofstream out(filename.c_str());
    if ( ! out ) return false;
    out << age << std::endl;
    return true;
  }
C++
1
2
Monstr Obj;
if(! Obj.writeFile("1.txt") ) std::cerr<<"Error!!!"<<std::endl;
Если использовать поток как член класса то после возникновении ошибки в потоке при i/o, класс может стать не работоспособным.
1
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 13:48  [ТС] 14
Можно еще кстати его как статическое поле объявить: static std::ofstream out;=)
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2012, 13:52 15
Можно еще кстати его как статическое поле объявить: static std::ofstream out;=)
Ну это проблемы с ошибками не решит, в отличии от локализации.
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 13:53  [ТС] 16
хорошо, спасибо)
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
29.07.2012, 14:06 17
Итак, для использования fstream как члена класса требуются веские основания. Но если такие основания есть и требуется обеспечить копирование объектов класса, содержащего какой-либо разделяемый ресурс (не только fstream), то можно воспользоваться "умными" указателями с подсчётом ссылок, например std::shared_ptr (для C++11) или boost::shared_ptr.
0
2 / 2 / 1
Регистрация: 21.11.2011
Сообщений: 183
29.07.2012, 23:24  [ТС] 18
ведь для использования shared_ptr надро подключить
C++
1
#include <boost/shared_ptr.hpp>
? Просто у меня он не находит такого файла (MVS2010)...

Добавлено через 23 минуты
Я правильно все сделал?

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// tesssst.cpp: определяет точку входа для консольного приложения.
//
 
#include "stdafx.h"
//#include <boost/shared_ptr.hpp>
#include <fstream>
#include <memory>
 
    class Monstr
    {
        private:
 
            static int count;
            std::string file_name;
            std::shared_ptr<std::ofstream>out;
        public:
            Monstr(std::string file_name = "test") : out(new std::ofstream(file_name, std::ios::app | std::ios::out))
            {
                this->file_name = file_name;
            //  std::ofstream out(file_name, std::ios::app | std::ios::out);
                *out << "constructor" << std::endl;
                //(*out).close();
            }
            Monstr(const Monstr &);
            ~Monstr()
            {
                //std::ofstream out("test", std::ios::app | std::ios::out);
                *out << "destructor" << std::endl;
                (*out).close();
            }
            void OUT()const{ 
                //std::ofstream out("test", std::ios::app | std::ios::out); 
                count++; 
                (*out) << "count = " << count << std::endl;
            //  out.close();
            }   
    };
 
    int Monstr::count;
 
    Monstr::Monstr(const Monstr & monstr)
    {
        this->file_name = monstr.file_name;
        //std::ofstream out("test", std::ios::app | std::ios::out);
        out = monstr.out;
        (*out) << "constructor_copy" << std::endl;
    //  (*out).close();
    }
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    Monstr Y;
    Monstr X(Y);
    X.OUT();
    Y.OUT();
    system("pause");
    return 0;
}
Добавлено через 2 минуты
В чем различие между shared_ptr из <boost/shared_ptr.hpp> и из <memory> ? И почему файл не находится?
0
Эксперт С++
8385 / 6147 / 615
Регистрация: 10.12.2010
Сообщений: 28,683
Записей в блоге: 30
29.07.2012, 23:25 19
Сначало надо установить boost
0
Эксперт С++
2381 / 1665 / 279
Регистрация: 29.05.2011
Сообщений: 3,399
30.07.2012, 02:06 20
Цитата Сообщение от Alberto_Timakov Посмотреть сообщение
В чем различие между shared_ptr из <boost/shared_ptr.hpp> и из <memory> ? И почему файл не находится?
В том, что сначала он появился в boost и только потом был включён в библиотеку языка. Так что если устраивает невозможность компиляции старыми компиляторами, то можно обойтись и без boost.
Если нужен буст и он уже установлен, то надо указать компилятору директорию с заголовочными файлами (ту, в которой расположена директория boost с заголовками). Где-то в настройках проекта, наверное, я не знаток VS2010.
В коде, на первый взгляд, всё нормально. В принципе деструктор и конструктор копии при этом необязательны, но и хуже от них не станет.
1
30.07.2012, 02:06
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
30.07.2012, 02:06
Помогаю со студенческими работами здесь

Создать класс вектор, содержащий элементы типа long double, размерность вектора
срочно!!!!!!!!!!! Пожалуйстаааа Задание 3. Создать класс вектор, содержащий элементы типа long...

Объявить класс, содержащий поле целого типа две константы, задающие допустимый диапазон
задание такое :5. Объявить класс, содержащий поле целого типа две константы, задающие допустимый...

Создайте класс Тест, содержащий две закрытые переменные типа int с именами count и max

Определить класс химический элемент, содержащий информацию о названии элемента его химических свойствах. Определить класс медикаменты, содержащий разн
Определить класс химический элемент, содержащий информацию о названии элемента его химических...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru