Avatar billede mxs Nybegynder
03. november 2005 - 01:02 Der er 18 kommentarer

Gemme et objekt i en vektor

Hej

Jeg har et problem som jeg har stirret mig blindt på. Jeg har denne klasse, fileBuf, som faktisk bare pusher en fileStream på en vector, men den giver rimlig mange fejl, eller faktisk bare en stor.

fileBuf.cpp
class fileBuf
{
public:
  void updateFile(fileStream);

private:
  vector<fileStream> buffer;
};

void fileBuf::updateFile(fileStream f)
{

  buffer.push_back(f);

}

og min fileStream.cpp
class fileStream
{
public:
  void setFile(string);
  string returnFile();
  ifstream & returnIfStream();

private:
  ifstream f;
};

using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "fileHandling.h"
#include "FileBuffer.cpp"

ifstream & fileStream::returnIfStream()
{
  return f;
}

void  fileStream::setFile(string g)
{

  f.open(g.c_str());

}


string fileStream::returnFile()
{

  string s;
  string fullFilled;

  if(!f)
    {

      fullFilled = "Filen kunne ikke aabnes";

    }else
      {

        while(getline(f,s))
          fullFilled += s;

      }

  return fullFilled;

}


int main()
{
  fileStream ny;
  ny.setFile("ha.txt");
  cout << ny.returnFile() << endl;
  return 0;
}

Fejlen jeg får er
In file included from fileHandling.cpp:7:
/usr/include/c++/3.3/bits/ios_base.h: I copy constructor 'std::basic_ios<char,
  std::char_traits<char> >::basic_ios(const std::basic_ios<char,
  std::char_traits<char> >&)':
/usr/include/c++/3.3/bits/stl_construct.h:78:  instantiated from `void std::_Construct(_T1*, const _T2&) [with _T1 = fileStream, _T2 = fileStream]'
/usr/include/c++/3.3/bits/stl_vector.h:599:  instantiated from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = fileStream, _Alloc = std::allocator<fileStream>]'
FileBuffer.cpp:7:  instantiated from here
/usr/include/c++/3.3/bits/ios_base.h:668: error: `std::ios_base::ios_base(const
  std::ios_base&)' is private
/usr/include/c++/3.3/bits/stl_construct.h:78: error: within this context
/usr/include/c++/3.3/streambuf: I copy constructor 'std::basic_filebuf<char,
  std::char_traits<char> >::basic_filebuf(const std::basic_filebuf<char,
  std::char_traits<char> >&)':
/usr/include/c++/3.3/bits/stl_construct.h:78:  instantiated from `void std::_Construct(_T1*, const _T2&) [with _T1 = fileStream, _T2 = fileStream]'
/usr/include/c++/3.3/bits/stl_vector.h:599:  instantiated from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = fileStream, _Alloc = std::allocator<fileStream>]'
FileBuffer.cpp:7:  instantiated from here
/usr/include/c++/3.3/streambuf:921: error: `std::basic_streambuf<_CharT,
  _Traits>::basic_streambuf(const std::basic_streambuf<_CharT, _Traits>&)
  [with _CharT = char, _Traits = std::char_traits<char>]' is private
/usr/include/c++/3.3/bits/stl_construct.h:78: error: within this context
/usr/include/c++/3.3/bits/ios_base.h: I member function 'std::basic_ios<char,
  std::char_traits<char> >& std::basic_ios<char, std::char_traits<char>
  >::operator=(const std::basic_ios<char, std::char_traits<char> >&)':
/usr/include/c++/3.3/bits/vector.tcc:230:  instantiated from `void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<_Tp*, std::vector<_Tp, _Alloc> >, const _Tp&) [with _Tp = fileStream, _Alloc = std::allocator<fileStream>]'
/usr/include/c++/3.3/bits/stl_vector.h:603:  instantiated from `void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = fileStream, _Alloc = std::allocator<fileStream>]'
FileBuffer.cpp:7:  instantiated from here
/usr/include/c++/3.3/bits/ios_base.h:671: error: `std::ios_base&
  std::ios_base::operator=(const std::ios_base&)' is private
/usr/include/c++/3.3/bits/vector.tcc:230: error: within this context
/usr/include/c++/3.3/streambuf: I member function 'std::basic_filebuf<char,
  std::char_traits<char> >& std::basic_filebuf<char, std::char_traits<char>
  >::operator=(const std::basic_filebuf<char, std::char_traits<char> >&)':
/usr/include/c++/3.3/streambuf:924: error: `std::basic_streambuf<_CharT,
  _Traits>& std::basic_streambuf<_CharT, _Traits>::operator=(const
  std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char, _Traits =
  std::char_traits<char>]' is private
/usr/include/c++/3.3/bits/vector.tcc:230: error: within this context

Jeg tror at det er fordi jeg har en ifstream i min fileStream og det måske er det som ødelægger det lidt, men jeg ved det ikke. Fejlen forkommer ihvertfald der hvor jeg prøver at pushe min fileStream i min vector i fileBuffer klassen.

Håber i vil hjælpe lidt?

Mvh.
Martin Slot
Avatar billede mxs Nybegynder
03. november 2005 - 01:04 #1
Undskyld. Mig der er dårlig til at paste, men afsnittet
class fileStream
{
public:
  void setFile(string);
  string returnFile();
  ifstream & returnIfStream();

private:
  ifstream f;
};

using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "fileHandling.h"
#include "FileBuffer.cpp"

Skal self. være

using namespace std;
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "FileBuffer.cpp"
class fileStream
{
public:
  void setFile(string);
  string returnFile();
  ifstream & returnIfStream();

private:
  ifstream f;
};

Sådan
Avatar billede bertelbrander Novice
03. november 2005 - 01:12 #2
Man kan ikke lave et kopi af en stream, når man kalder push_back laver man et kopi af det man push'er.

Du kan løse det ved at lade stream'en være en pointer eller ved at push'e en pointer i vector'en
Avatar billede mxs Nybegynder
03. november 2005 - 01:24 #3
Ved at pushe en pointer i vectoren. Mener du, at jeg skal lade updateFile se sådan her ud

updateFile(fileStream* f)
{
  buffer.push_back(&f);
}

?
Avatar billede bertelbrander Novice
03. november 2005 - 01:27 #4
Du er nødt til at new'e fileStream objectet (og delete det efter brug).
buffer bliver så:
  vector<fileStream *> buffer;

Og updateFile bliver:
updateFile(fileStream *f)
{
  buffer.push_back(f);
}
Avatar billede mxs Nybegynder
03. november 2005 - 01:31 #5
Haha, jeg vidste at det havde noget at gøre med den ifstream. Jeg havde så bare ikke lige regnet ud at jeg self. skulle have en pointer i vectoren så den bliver det du skriver. Hvad er det engentlig den gør ved, vector<fileStream*> buffer. Opretter den så en pointer til det man smider i den?
Avatar billede bertelbrander Novice
03. november 2005 - 01:38 #6
Vector'en holder så styr på en pointer; push_back laver et kopi af pointeren:

  fileStream *p = new fileStream;
  vector<fileStream *> buffer;
  buffer.push_back(p);
  buffer[0]->Whatever();
  delete buffer[0];
  buffer.erase(buffer.begin());
Avatar billede bertelbrander Novice
03. november 2005 - 01:43 #7
Det er iøvrigt ikke nogen gode idé at #include en .cpp fil.
Og g++'s (og de fleste andre compileres) fejlbeskeder ved brug af stl containere er "lidt" svære at tyde.
Avatar billede mxs Nybegynder
03. november 2005 - 01:46 #8
Sådan ja. Jamen hvad skal jeg så kalde den? .cpp og .h er de eneste to jeg skal bruge og jeg vil ikke have en hel masse klasser blandet sammen, da jeg selv synes det bliver for rodet, men måske er det, det eneste rigtige?
Avatar billede bertelbrander Novice
03. november 2005 - 02:05 #9
Så længe det er dine egne små projecter går det nok, men en dag vokser projectet og så får du for mange problemer med cirkulære afhængigheder.

Du børe lære at sætte et project op med mere end én .cpp fil, uden at #include .cpp filer. På linux (som det ser ud til at du bruger) indebærer det normalt at man bruger makefiler.
Avatar billede bertelbrander Novice
03. november 2005 - 02:08 #10
Overvej også lige om ikke det ville være lettere at lave en pointer til stream'en i class'en så du undgår at bruge pointere i vector'en, det er måske lettere at styre. Hvis du vælger den løsning bør du lave en copy constructor og assignment operator i class'en.
Avatar billede mxs Nybegynder
03. november 2005 - 02:16 #11
Laver jeg den pointer i klassen, så kan jeg ikke få min returnIfStream() til at virke :(

ifstream & fileStream::returnIfStream()
{
  return f;
}

Makefiles. Hmm, det må være det jeg skal bruge så. Må jeg lige kigge på.
Avatar billede mxs Nybegynder
03. november 2005 - 02:18 #12
Jeg er heller ikke inde i det med copy constructor og assignment operatoren. Altså det vil sige, at jeg godt ved hvordan man overloader en operator osv. men selve tankegangen har jeg ikke sat mig ind i, hvorfor den skal laves osv.
Avatar billede bertelbrander Novice
03. november 2005 - 02:26 #13
Det vil så blive:
ifstream *fileStream::returnIfStream()
{
  return f;
}
Eller:
ifstream &fileStream::returnIfStream()
{
  return *f;
}

Formålet med at lave copy constructor og assignment operator for din class her er at undgå at to instancer af class'en peger på det samme stream object, og at de begge delete'r den.

Følgende ser korrekt ud:
class X
{
public:
  X() { p = new int; }
  ~X() { delete p; }
  int *p;
};

Men hvis du så laver:
X x1;
X x2 = x1;
Så går det galt. Når x2 sætte lig med x1, vil de begge pege på den samme int, og de vil begge forsøge at delete den samme i destructoren.
Avatar billede mxs Nybegynder
03. november 2005 - 02:26 #14
Har fået det til at virke :) Dog uden copy constructoren og assignment operatoren.
Avatar billede bertelbrander Novice
03. november 2005 - 02:29 #15
Avatar billede mxs Nybegynder
03. november 2005 - 02:30 #16
Oooh det kan jeg godt sætte mig ind i!
Avatar billede mxs Nybegynder
03. november 2005 - 02:32 #17
Cool side. Vil jeg kigge nærmere på!! Jeg siger ihvertfald tak for hjælpen, Bertel og jeg får ud fra at du stadig ikke samler på points. Men smid et svar, hvis du i melllem tiden er blevet konverteret til pointsamler.
Avatar billede mxs Nybegynder
16. december 2008 - 21:01 #18
Jeg går ud fra at du ikke vil have pointene, selvom du var til en stor hjælp.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester