Übergabe von fstream im Konstruktor



  • Servus,

    ich beschäftge mich seit kurzem mit C++ und wollte eine Klasse Output erstellen, an die ich ein eine schon geöffnete Datei übergeben will. Ich hab mir gedacht ich probiere es mal so:

    #include <fstream>
    #include <iostream>
    
    using namespace std;
    
    struct Output {
      ofstream output;
    
      Output(ofstream *file) : output(*file) {}
    
      /** ... Funktion die in output hineinschreibt ... */
    };
    
    int main(int argc, char **argv)
    {
    
      return 0;
    }
    

    ... funzt aber nicht.

    Warum nicht? Wie mache ich es anders?

    Vielen Dank im Voraus,
    HarryKane



  • harrykane schrieb:

    ... funzt aber nicht. ...

    Aha - ist heute wieder Ratestunde ?

    Gruß,

    Simon2.

    P.S.: Analoge Frage: "Ich möchte gerne nachhause fahren, aber das funzt nicht - warum nicht ?"


  • Administrator

    Simon2, sei mal nicht so hart, ist ja sein erster Beitrag hier. Aber hast natürlich schon recht 🙂

    @HarryKane,
    Streams kann man nicht kopieren. Also musst du entweder eine Referenz oder Zeiger übergeben. Dabei aber beachten, dass der ursprüngliche Speicher nicht freigegeben wird, sonst knallt es 😉

    Grüssli



  • Dravere schrieb:

    Simon2, sei mal nicht so hart, ist ja sein erster Beitrag hier. ...

    Dann ist ihm ja der "Du brauchst Hilfe ?"-sticky-Thread ja noch ganz frisch in Erinnerung.
    Außerdem ist "Neusein" kein echter Grund gegen simples Nachdenken. Das hat ja noch nichtmal was mit C++ oder Internet zu tun....

    Gruß,

    Simon2.



  • Simon2 schrieb:

    Aha - ist heute wieder Ratestunde ?

    Sorry, kann dir gerne noch die Compilerausgabe hinzufügen, vllt wirst du daraus ja schlau:

    > g++ test.cc -o test -lm
    /usr/include/c++/4.1.2/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.1.2/bits/ios_base.h:779: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private
    /usr/include/c++/4.1.2/iosfwd:55: error: within this context
    /usr/include/c++/4.1.2/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.1.2/iosfwd:92: 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.1.2/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.1.2/streambuf:781: 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.1.2/iosfwd:86: error: within this context
    /usr/include/c++/4.1.2/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.1.2/iosfwd:92: 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
    test.cc: In constructor ‘Output::Output(std::ofstream*)’:
    test.cc:24: note: synthesized method ‘std::basic_ofstream<char, std::char_traits<char> >::basic_ofstream(const std::basic_ofstream<char, std::char_traits<char> >&)’ first required here
    

    Dravere schrieb:

    @HarryKane,
    Streams kann man nicht kopieren. Also musst du entweder eine Referenz oder Zeiger übergeben. Dabei aber beachten, dass der ursprüngliche Speicher nicht freigegeben wird, sonst knallt es 😉

    Grüssli

    Ich stehe gerade auf dem Schlauch, ich dachte ich übergebe hier einen Zeiger auf den ofstream? *dumm guck*



  • Du übergibst einen Zeiger, aber konstruierst "output" per Copy-Konstruktor.
    Statt ein neues Objekt zu erstellen, verwende das Übergene.

    Entweder mit Zeiger:

    struct Output {
      ofstream* output;
    
      Output(ofstream *file) : output(file) {}
    };
    

    oder mit Referenz:

    struct Output {
      ofstream& output;
    
      Output(ofstream& file) : output(file) {}
    };
    


  • Ok, danke, das klappt. Nun muss ich nur noch mal drüber meditieren, was ich da eigentlich mache 🙂 (Schlimm, wenn man immer nur über trial&error lernt ...)

    Vielen Dank auf jeden Fall für die schnelle Hilfe.



  • harrykane schrieb:

    ...
    Sorry, kann dir gerne noch die Compilerausgabe hinzufügen, vllt wirst du daraus ja schlau:...

    Danke.

    Ja - aber so schwer ist das auch nicht:

    harrykane schrieb:

    ...

    > ...In copy constructor ...std::basic_ios...: error: ‘std::ios_base::ios_base(const std::ios_base&)’ is private...
    

    Der Copy-Konstruktor ist private .... darf also von "außen" nicht aufgerufen werden. Das ist eine beliebte Technik, um das sicherzustellen, was Dravere formuliert hat: Die Dinger soll man nicht kopieren !
    Vermutlich versuchst Du das in Deinem Konstruktor so in der Art:

    struct Output {
      ofstream output; // ein ofstream-Objekt
    
      Output(ofstream *file) : output(*file) {} // <- Hier wird der ofstream-Copy-Construktor (ist nur ein "Speziaslfall" von basic_ios) aufgerufen, 
       // .. der wiederum den ios_base-Copy-Constructor aufruft, ...
       // .. der aber private ist
    };
    

    😃

    Im Gegensatz dazu hat Draveres Lösung genau ein Zeichen (* oder &) an einer anderen Stelle, das den entscheidenden Unterschied macht:

    struct Output {
      ofstream* output; // <- Dein Output-Objekt hält einen ofstream-ZEIGER !!!
      Output(ofstream *file) : output(file) {} // <- Hier wird nur ein Zeiger kopiert !! 
    };
    

    oder

    struct Output {
      ofstream& output; // <- Dein Output-Objekt hält eine ofstream-REFERENZ !!!
      Output(ofstream& file) : output(file) {} // <- Hier wird nur eine Referenz initialisiert
    };
    

    ...oder Mischformen davon (Referenz mit *file initialisiert oder Zeiger auf Adresse des referenzierten Objekts zeigern lassen).
    In keinem dieser Fälle wird der ofstream-Copy-Constructor verwendet.

    (BTW: "funzt net" kann auch heißen "compiliert fehlerlos aber macht was Anderes als ich erwartet habe" oder "Programm stürzt beim Start ab" oder "Lässt sich nicht auf dem PC meiner Freundin installieren" oder ....)

    Gruß,

    Simon2.


Anmelden zum Antworten