lunedì 3 gennaio 2011

C++: problemi con copia oggetti stream

Il seguente errore di compilazione (probabilmente contornato da alcune altre righe relative al nostro specifico codice) restituito dal compilatore g++ per un programma scritto in C++ è sintomo di un problema molto specifico e subdolo:

/usr/include/c++/4.4/bits/ios_base.h:
In copy constructor ‘std::basic_ios< char,
std::char_traits< char> >::basic_ios(const std::basic_ios< char,
std::char_traits< char> >&)’:
/usr/include/c++/4.4/bits/ios_base.h:790: error:
‘std::ios_base::ios_base(const std::ios_base&)’ is private
/usr/include/c++/4.4/iosfwd:47: error: within this context
/usr/include/c++/4.4/iosfwd:
In copy constructor ‘std::basic_ofstream< char,
std::char_traits< char> >::basic_ofstream(const std::basic_ofstream< char,
std::char_traits< char> >&)’:
/usr/include/c++/4.4/iosfwd:84:
note: synthesized method ‘std::basic_ios< char,
std::char_traits< char> >::basic_ios(const std::basic_ios< char,
std::char_traits< char> >&)’ first required here
/usr/include/c++/4.4/streambuf:
In copy constructor ‘std::basic_filebuf< char,
std::char_traits< char> >::basic_filebuf(const std::basic_filebuf< char,
std::char_traits< char> >&)’:
/usr/include/c++/4.4/streambuf:770:
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++/4.4/iosfwd:78: error: within this context
/usr/include/c++/4.4/iosfwd:
In copy constructor ‘std::basic_ofstream< char,
std::char_traits< char> >::basic_ofstream(const std::basic_ofstream< char,
std::char_traits< char> >&)’:
/usr/include/c++/4.4/iosfwd:84:
note: synthesized method ‘std::basic_filebuf< char,
std::char_traits< char> >::basic_filebuf(const std::basic_filebuf< char,
std::char_traits< char> >&)’ first required here

Tutte queste parole in realtà possono essere sintetizzate in questo modo: state cercando di copiare un oggetto che non può essere copiato. L'oggetto in questione è, in questo caso, uno stream della libreria standard (nel mio caso era un oggetto della classe ofstream).
Importante è ricordare che anche quando si passa un oggetto (o, più in generale, una variabile) ad una funzione il codice corrispondente all'invocazione della funzione genererà una copia dell'oggetto passato, anche in questo caso si compie quindi un'operazione non valida e il compilatore ci dirà, in modo non troppo chiaro, che stiamo sbagliando.

La soluzione al problema è molto semplice: è sufficiente modificare la funzione e la sua invocazione in modo che quello ad essere passato sia il riferimento (cioè il puntatore) all'oggetto e non l'oggetto stesso.

Versione errata:
  class myclass {  
...
public:
void print(ofstream file) const;
};

[...]

ofstream file;
file.open(filename,ios::out);
myclass obj();
obj.print(file);

Versione corretta:
  class myclass {  
...
public:
void print(ofstream *file) const;
};

[...]

ofstream file;
file.open(filename,ios::out);
class obj();
obj.print(&file);

Nessun commento:

Posta un commento