How this file class works? (C++)

h4ever

Member
Aug 30, 2013
163
0
0
In a project that I have downloaded from net I found a class which should provide auto open and auto close of file. There are some points which are not clear to me, maybe you can explain?

type definition
Code:
#ifndef _FILE_DEFINED
struct _iobuf {
        char *_ptr;
        int   _cnt;
        char *_base;
        int   _flag;
        int   _file;
        int   _charbuf;
        int   _bufsiz;
        char *_tmpfname;
        };
typedef struct _iobuf FILE;
#define _FILE_DEFINED
#endif

typedef struct _iobuf FILE;
http://paste.ofcode.org/BiYFiEGysER7FHFX25FPMy

header file
Code:
// @return the file's size, in bytes.
long fsize(const char *path); // TODO: take a FILE*

// AutoFile closes file - see utilio.cpp for definition
class AutoFile
{
public:
    AutoFile(FILE * file);
    AutoFile(const char * filename, const char * mode);
    ~AutoFile();
    FILE * get();
    void close();     // Close the file. Further calls to get() will return NULL.
private:
    AutoFile(const AutoFile&); // no copy constructor!
    FILE * _file;
};

inline FILE * AutoFile::get()
{
    return _file;
}
http://paste.ofcode.org/B6PSp3XTrCLw5q59vpysFD

The definition:
Code:
long fsize(const char *path)
{
    AutoFile file(path, "rb");
    fseek(file.get(), 0, SEEK_END);    
    return ftell(file.get());
    // AutoFile closes file
}

AutoFile::AutoFile(const char * filename, const char * mode)
:    _file(fopen(filename, mode))
{
    if (!_file)
        throw io_error("Could not open file.");
}

void AutoFile::close()
{
    if (_file)
        fclose(_file);
}

AutoFile::~AutoFile()
{
    close();
}

AutoFile::AutoFile(const AutoFile &)
{
    // never called
}
http://paste.ofcode.org/qgBVD47qeTN7NYywA7Dw5X

I would like to know what is the type FILE for. I know that it is pointer, but don't understand why the class needs it. How does the class initiate the data into _file? I see get() only returns the _file. Now I see that _file is also a function... _file(fopen(filename, mode)) ... So is this some special case when the _file variable is filled with a content from the result in the argument _file(..) function because it has same name like the variable?

Also AutoFile constructor seems to be empty, so how the function _file is called? Looks it must be auto.

The AutoFile is used like so:
Code:
AutoFile tempout(dpath, "wb");
AutoFile scx(path, "wb");
AutoFile temp(dpath, "rb");
AutoFile dc2in(path, "rb");
AutoFile textout(path, "w");
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
There is no function _file(). What you see is the initialization of a class member variable in member initialization list.

FILE is a struct that standard C functions like fopen(), fclose(), fscanf(), etc seem to use. It makes no sense that this source redefines it.
 

h4ever

Member
Aug 30, 2013
163
0
0
may you explain why the class member is initiated in this way in the brackets?

Code:
AutoFile::AutoFile(const char * filename, const char * mode)
:    _file(fopen(filename, mode))
Why it does not use like
Code:
AutoFile::AutoFile(const char * filename, const char * mode)
:    _file=fopen(filename, mode)
 

h4ever

Member
Aug 30, 2013
163
0
0
One more question:
In the initiation of the object:
Code:
AutoFile::AutoFile(const char * filename, const char * mode)
:    _file(fopen(filename, mode))
where does it take the arguments filename and mode?

Is it like so, that the constructor is filled with arguments?
Code:
AutoFile::AutoFile(const AutoFile &)
{
    // never called
}
I see only one argument, Auto file, but not the mode...
On the other hand during the call of the AutoFile wrapper I see:
Code:
AutoFile scx(path, "wb");
Does this mean that AutoFile creates scx pointer to the scx file? Probably yes, because I have found scx.get() which returns the handler of the file. Also I have found temp.get() and even temp.close()...

So there in the class declaration the word FILE refers to scx obkject or temp object... as a handler to the type _file, which contains the function to get the handler and to close the file.... ???

But that's the role of inline here?
Code:
inline FILE * AutoFile::get()
{
    return _file;
}
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
You should read a lot more about syntax of C++ (classes).

There is no name set for the parameter taken by the copy constructor, only the type. The whole implementation is unnecessary, because the compiler makes one for you. The key point is that the copy constructor is declared in the private section of the class so that no outsider can ever invoke it.

Keyword 'inline' ... "And thirdly, the code is more what you'd call "guidelines" than actual rules. Welcome aboard the Black Pearl, Miss Turner."

A statement
Code:
AutoFile scx(path, "wb");
does call the constructor
Code:
AutoFile::AutoFile( const char *, const char * )


You code lacks implementation for
Code:
AutoFile::AutoFile( FILE * )
and that is an error.
 

h4ever

Member
Aug 30, 2013
163
0
0
A statement
Code:
AutoFile scx(path, "wb");
does call the constructor
Code:
AutoFile::AutoFile( const char *, const char * )

Code:
AutoFile::AutoFile(const char * filename, const char * mode)
:    _file(fopen(filename, mode))
{
    if (!_file)
        throw io_error("Could not open file.");
}
This is a constructor? I thought it is class member definiiton list...

What does mean the argument AutoFile in the constructor implementation?

Code:
AutoFile::AutoFile(const AutoFile &)
{
}
Having its own class name in the argument looks weird to me, even that the author does not use it.
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
MyClass::MyClass( const MyClass& other ) :
x( other.x ), c( other.c ), s( other.s )
{}

What they mean by the word other? Is it name of the new class? For the copy?
 

h4ever

Member
Aug 30, 2013
163
0
0
You should read a lot more about syntax of C++ (classes).

There is no name set for the parameter taken by the copy constructor, only the type. The whole implementation is unnecessary, because the compiler makes one for you. The key point is that the copy constructor is declared in the private section of the class so that no outsider can ever invoke it.

So why he added the copy constructor to arguments when he wants not to use it or he does not want to call the constructor directly*?

*
Code:
AutoFile::AutoFile(const AutoFile &)
{
    // never called
}
 

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
MyClass::MyClass is a function. It takes one parameter, which is a const reference to object of type MyClass. Name "other" is assigned to the parameter. The parameter is dereferenced in the initializer list. It is no different from the use of bar in:
Code:
void foo( int bar ) {
  std::cout << bar;
}

Compiler does create a copy constructor for each class, if you don't. It does make it a public member function. When we write the declaration in the private section, it is a private member function. Can I assume that you know what public and private members of a class mean?
 

h4ever

Member
Aug 30, 2013
163
0
0
Yeah, I read the classes tutorial on cplusplus.com, I also am used to use classes in PHP.

Ah, so he written it to make the copy constructor private. Good. Thanks for explanation.

So basically, this is how the copy constructor is created:

MyClass::MyClass( const MyClass& )

or

MyClass::MyClass( const MyClass& other)

But in the case that there are the the next items after the : so this is initiation of the new members, right? If I understand this, correctly, so the next part is the initializer list (correctly called member initialization list). ...

MyClass::MyClass( const MyClass& other ) :
x( other.x ), c( other.c ), s( other.s )
{}
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
In the public declaration there is:
Code:
 AutoFile(FILE * file);
But I still don't understand how the file is defined.

I see this definition later in the fsize function:
Code:
AutoFile file(path, "rb");
But I don't see any case of the definition with single argument.

Edit:
Ah, mv2devnull pointed it here already:
You code lacks implementation for.. and that is an error
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
Code:
AutoFile file(path, "rb");
That is neither function declaration nor definition.

It is a declaration of variable named "file" with type "class AutoFile" and the variable is initialized during declaration with two values: {variable named "path", string literal "rb"}. Such initialization implicitly calls a constructor of class AutoFile. A constructor that takes two parameters, whose types are {typeof(path), const char *} (or convertible from those).
 

h4ever

Member
Aug 30, 2013
163
0
0
That is neither function declaration nor definition.

I thought about file definition... but you are right that there is not file declared in the class so it must be declared first.


Code:
AutoFile file(path, "rb");
It is a declaration of variable named "file" with type "class AutoFile" and the variable is initialized during declaration with two values: {variable named "path", string literal "rb"}. Such initialization implicitly calls a constructor of class AutoFile. A constructor that takes two parameters, whose types are {typeof(path), const char *} (or convertible from those).

I think I missed the "glue", which is here:
  • Initialization of data members in a class and objects. Classes with a user-defined constructor require a constructor's member initialization list (mem-init for short) for their data members. An object's initializers are enclosed in parentheses in the object's declaration://C++03 initialization of classes and objects
    Code:
    struct S1
    {
    explicit S1(int n, int m) : x(n), y(m){} //mem-init
    private:
     int x, y;
    };
    S1 s(0,1); //object initializers enclosed in parentheses
    S1 s2={0,1}; //compilation error
I believe this could more exact ...
  • The constructor of class AutoFile, which is called by the command, initiates variable file with values {variable named "path", string literal "rb"}. So these types are const char * filename, const char * mode
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
How would look equivalent statement of this
Code:
AutoFile scx(path, "wb");
Should it look something like
Code:
Autofile scx = new Autofile::Autofile(arg1, arg2)
? Or would it be not possible to initiate the values in one statement when I would decide to use operator new?
 

brandonb

Diamond Member
Oct 17, 2006
3,731
2
0
How would look equivalent statement of this
Code:
AutoFile scx(path, "wb");
Should it look something like
Code:
Autofile scx = new Autofile::Autofile(arg1, arg2)
? Or would it be not possible to initiate the values in one statement when I would decide to use operator new?

Doing a new means you are using a pointer. But it works just like a local variable. The only difference is rather than using stack space, it goes into heap (if I remember right!). Stack means once the function exits, so does the memory that holds that variable. Using a pointer (or *) on the variable and doing a new on it means the variable goes into heap, or global memory throughout the program.

Code:
Autofile [b]*[/b]scx = new Autofile::Autofile(arg1, arg2)

Is the same as:

Code:
AutoFile scx(arg1, arg2);

The only difference is where this variable is stored in memory.

Just don't forget to

Code:
delete scx;

When using a pointer. Otherwise that memory is not cleared, and you'll have a memory leak. Stack memory is cleared by default when the function ends, but heap memory (or done through the new keyword) has to be deleted manually when appropriate.

Just to clarify before someone wants to kick my ass:

Code:
Autofile [b]*[/b]scx = new Autofile::Autofile(arg1, arg2)

If you use this in a local function, that pointer variable will be deleted when it goes out of scope and the function ends, but the object created in heap memory will still persist. If that pointer variable disappears, you won't know which memory location that object is at when you want to delete it later. So you should really understand pointers before continuing.
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
Code:
Autofile [B]*[/B]scx = new Autofile::Autofile(arg1, arg2)
Is the same as:

Code:
AutoFile scx(arg1, arg2);
The only difference is where this variable is stored in memory.
Not quite.

Code:
// Construct a local variable that has type "AutoFile".
// Initialize it with its constructor that takes at least two parameters,
// using data from arg1 and arg2
// (assuming types of arg1 and arg2 are appropriate)
AutoFile scx(arg1, arg2);


// Allocate memory from free store and initialize it with the same
// constructor of AutoFile that the 'scx' was constructed with
//
// Construct a local variable 'psx' that has type "pointer to AutoFile object".
// Initialize 'psx' with the address of the dynamically allocated memory block
AutoFile *psx = new AutoFile(arg1, arg2);
 

h4ever

Member
Aug 30, 2013
163
0
0
So Stack "temporal" memory of function and Heap = global memory of program.

If that pointer variable disappears, you won't know which memory location that object is at when you want to delete it later
Thanks for explanaiton. This explains memory leaks.

But could you pls explain me relations of "Native objects" and "Managed objects" and "Garbage collector" with this two memories? Is there some relation or difference of what exists in which memory?
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
FILE * is in C standard.
Operator new is in C++ standard.
Automatic garbage collection is in neither.