Problem with initialization of poiter to the file stream

Discussion in 'C++' started by Anton Pervukhin, Oct 4, 2005.

  1. Hi everybody!

    I have a small problem regarding the initialization of pointer to the
    file stream under some conditions.
    Imagine a class which has a pointer to output file stream and some
    additinional methods to deal with it, i.e. open/close/write:

    classA {
    private:
    const std::auto_ptr<std::eek:fstream> filePtr;
    std::_Ios_Openmode mode;
    public:
    classA(const std::string& name, bool isAppended = true);
    virtual ~ClassA{};
    void setAppended(bool isAppended);
    bool isAppended();
    bool reopen();
    void close();
    }

    The usage of std::eek:fstream in my case is well suited to be defined as
    auto_ptr.
    There is also a variable "mode" which defines in which mode file should
    be opened (i.e. appended, truncated etc)

    Now I'm trying to write a constructor to set both private variables.
    Clearly I would like to open "filePtr" with the mode given by
    "isAppended" formal variable.

    classA::ClassA(const std::string& fileName, bool isAppended) {
    this->setAppended(isAppended); // to set
    mode
    *filePtr = *(new std::eek:fstream(fileName.c_str(), mode)); //
    Compile error
    }

    which leads to a compilation error that std::ios_base::eek:perator= is
    private.

    I could set filePtr in initialization list like this:

    ClassA::ClassA(const std::string& fileName, bool isAppended):
    filePtr(new std::eek:fstream(fileName.c_str())){
    this->setAppended(isAppended);
    }

    but then at the moment of "filePtr" initialization its "mode" is not
    known yet, meaning that "filePtr" should be reopened again later with
    the right "mode".

    Putting initialization of "mode" in a list before "filePtr" doesn't
    guarantied that it will be initialized before.

    There is a solution to make function "setAppended" returns bool and put
    it this way:

    ClassA::ClassA(const std::string& fileName, bool isAppended):
    filePtr(new std::eek:fstream(fileName.c_str(),
    this->setAppended(isAppended))){
    }

    which looks rather ugly... Putting in the same place the code of
    function "setAppended" instead of calling it, duplicates the code.

    So all in all I'm wondering whether "filePtr" could be initialized
    somehow but in the constructor body and not its initialization list.

    the case with using reference like this...

    ///
    std::eek:fstream& fileRef;
    ....
    std::eek:fstream tempRef(fileName.c_str(), mode);
    fileRef = tempRef;
    ///

    ...won't work because I cannot define reference for auto_ptr like this:
    const std::auto_ptr<std::eek:fstream&> filePtr


    Any tips will be appreciated!

    regards,
    Anton
    Anton Pervukhin, Oct 4, 2005
    #1
    1. Advertising

  2. Anton Pervukhin

    Rolf Magnus Guest

    Anton Pervukhin wrote:

    > Hi everybody!
    >
    > I have a small problem regarding the initialization of pointer to the
    > file stream under some conditions.
    > Imagine a class which has a pointer to output file stream and some
    > additinional methods to deal with it, i.e. open/close/write:


    #include <memory>
    #include <string>
    #include <ostream>
    #include <fstream>

    > classA {


    class classA

    > private:
    > const std::auto_ptr<std::eek:fstream> filePtr;
    > std::_Ios_Openmode mode;
    > public:
    > classA(const std::string& name, bool isAppended = true);
    > virtual ~ClassA{};


    virtual ~classA{}


    > void setAppended(bool isAppended);
    > bool isAppended();
    > bool reopen();
    > void close();
    > }


    ;

    > The usage of std::eek:fstream in my case is well suited to be defined as
    > auto_ptr.


    Your class doesn't correctly handle copying, which would be disaterous with
    an auto_ptr as member.

    > There is also a variable "mode" which defines in which mode file should
    > be opened (i.e. appended, truncated etc)
    >
    > Now I'm trying to write a constructor to set both private variables.
    > Clearly I would like to open "filePtr" with the mode given by
    > "isAppended" formal variable.
    >
    > classA::ClassA(const std::string& fileName, bool isAppended) {
    > this->setAppended(isAppended); // to set
    > mode
    > *filePtr = *(new std::eek:fstream(fileName.c_str(), mode)); //
    > Compile error


    Why are you dereferencing?

    Try:
    filePtr = new std::eek:fstream(fileName.c_str(), mode);

    > }
    >
    > which leads to a compilation error that std::ios_base::eek:perator= is
    > private.
    >
    > I could set filePtr in initialization list like this:
    >
    > ClassA::ClassA(const std::string& fileName, bool isAppended):
    > filePtr(new std::eek:fstream(fileName.c_str())){


    You're not dereferencing here.

    > this->setAppended(isAppended);
    > }
    >
    > but then at the moment of "filePtr" initialization its "mode" is not
    > known yet, meaning that "filePtr" should be reopened again later with
    > the right "mode".
    >
    > Putting initialization of "mode" in a list before "filePtr" doesn't
    > guarantied that it will be initialized before.


    It's guaranteed that it won't. That's because you declared "mode" after
    "filePtr". Members are always initialized in the order they are declared
    in.

    > There is a solution to make function "setAppended" returns bool and put
    > it this way:
    >
    > ClassA::ClassA(const std::string& fileName, bool isAppended):
    > filePtr(new std::eek:fstream(fileName.c_str(),
    > this->setAppended(isAppended))){
    > }
    >
    > which looks rather ugly... Putting in the same place the code of
    > function "setAppended" instead of calling it, duplicates the code.
    >
    > So all in all I'm wondering whether "filePtr" could be initialized
    > somehow but in the constructor body and not its initialization list.


    Initializations can only be done in the initializer list.

    > the case with using reference like this...
    >
    > ///
    > std::eek:fstream& fileRef;
    > ...
    > std::eek:fstream tempRef(fileName.c_str(), mode);
    > fileRef = tempRef;
    > ///
    >
    > ..won't work because I cannot define reference for auto_ptr like this:
    > const std::auto_ptr<std::eek:fstream&> filePtr


    I'm wondering why you don't just add an _instance_ of std::eek:fstream as a
    member.
    Rolf Magnus, Oct 4, 2005
    #2
    1. Advertising

  3. > Your class doesn't correctly handle copying, which would be disaterous with
    > an auto_ptr as member.


    why it should be disasterous with an auto_ptr as member?
    If I disable copy constructor and assignment operator, will it be still
    dangerous to use auto_ptr?

    > Why are you dereferencing?
    >
    > Try:
    > filePtr = new std::eek:fstream(fileName.c_str(), mode);


    In case with filePtr definition as auto_ptr this statement won't
    compile.

    > I'm wondering why you don't just add an _instance_ of std::eek:fstream as a
    > member.


    Good question ;-) I just decided to give a try to use auto_ptr, since
    the class is not going to be copied or assigned.
    Anton Pervukhin, Oct 4, 2005
    #3
  4. Anton Pervukhin wrote:
    >
    > > Your class doesn't correctly handle copying, which would be disaterous with
    > > an auto_ptr as member.

    >
    > why it should be disasterous with an auto_ptr as member?


    because it has a wrong copy semantics. For the same reason auto_ptr
    cannot be used in a container.

    > If I disable copy constructor and assignment operator, will it be still
    > dangerous to use auto_ptr?


    Then you are fine. But you didn't :)

    >
    >
    > > I'm wondering why you don't just add an _instance_ of std::eek:fstream as a
    > > member.

    >
    > Good question ;-) I just decided to give a try to use auto_ptr, since
    > the class is not going to be copied or assigned.


    Thats not a good reason. Your first question should be: Do I need to allocate
    dynamically or not. Only then, after you decided that you need dynamic allocation
    you can ask the question if some smart pointer is the way to go.
    But in your case, I really see no reason why the stream object has to be allocated
    with new. Especially because you say you don't want to copy or assign such an object.
    Whats wrong with using an ordinary ofstream member and open the file with open()?

    --
    Karl Heinz Buchegger
    Karl Heinz Buchegger, Oct 4, 2005
    #4
  5. > Thats not a good reason. Your first question should be: Do I need to allocate
    > dynamically or not. Only then, after you decided that you need dynamic allocation
    > you can ask the question if some smart pointer is the way to go.
    > But in your case, I really see no reason why the stream object has to be allocated
    > with new. Especially because you say you don't want to copy or assign such an object.
    > Whats wrong with using an ordinary ofstream member and open the file with open()?


    I see your point and need to reconsider mine :) Thanks for
    explanation.
    Anton Pervukhin, Oct 4, 2005
    #5
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. JKop
    Replies:
    10
    Views:
    924
  2. Matthias Kaeppler
    Replies:
    2
    Views:
    429
    Victor Bazarov
    Jul 18, 2005
  3. Replies:
    6
    Views:
    451
    Ron Natalie
    Dec 11, 2005
  4. Replies:
    9
    Views:
    614
    Alex Buell
    Apr 27, 2006
  5. toton
    Replies:
    5
    Views:
    920
    Victor Bazarov
    Sep 28, 2006
Loading...

Share This Page