Dereference operator overload issues

Hello, my code is almost done but there is one last thing i can't deal with.
So the point of it is: I have a file containts 10 int values in binary and i need to print them to console backward and forward using my custom Iterator.

But my Dereference operator does not work, any suggestions?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  #include <iostream>
#include <cstdio>


using namespace std;


class IntFile
{
public:
    //int index = 0;
    int value;
    FILE* file;
    IntFile() {}
    ~IntFile() {}
    int mnumbers[10];

    // get value from current index in file
    int& getValue(int index)
    {
        fseek(file, 4*index, SEEK_SET);
        fread(&value, 4, 1, file);
        return value;
    }

    friend struct iterator;
    struct iterator
    {
        int index = 0;
        int value = 0;

        iterator(FILE* ptrfile, int idx)
        {
            index = idx;
            fseek(ptrfile, 4*index, SEEK_SET);
        }
        bool operator==(const iterator&other) const
        {
            return index == other.index;
        }
        bool operator!=(const iterator&other) const
        {
            return index!=other.index;
        }

        int &operator*()
        {
            return IntFile::getValue(index);
        }
        iterator&operator++()
        {
            this->index = index+1;

        }
        iterator&operator--()
        {
            this->index = index -1;
        }
    };
    iterator begin()
    {
        return iterator(file, 0);
    }
    iterator end()
    {
        return iterator(file, 9);
    }
};


int main()
{
    IntFile file;
    int A;


    file.file = fopen("text.txt", "r+b");

    cout << "FORWARD: " << endl;
    for (IntFile::iterator i = file.begin(); i != file.end(); ++i)
    {
        cout << "++ test ";
    }

    cout << endl << "BACKWARD: " << endl;
    for (IntFile::iterator i = file.end(); i != file.begin(); --i)
    {
        cout << "-- test ";
    }

    A = file.getValue(5); // This was made to test if function works and it works fine.
    cout << endl << "A: " << A << endl;

    ////////////////////////////////////////
    fclose(file.file);
    return 0;
}




So should i call return IntFile::getValue(index) with int index or with just index?

If I use return IntFile::getValue(index); then the error would be
error: cannot call member function 'int& IntFile::getValue(int)' without object|


If I use return IntFile::getValue(int index); then there is another error
error: expected primary-expression before 'int'


I think I have to return a bit differently or I should change the getValue function itself.
Last edited on

While I'm here, this looks very odd:

1
2
3
4
       iterator&operator--()
        {
            this->index = index -1;
        }


The this-> is unnecessary. It would be better written:

1
2
3
4
       iterator&operator--()
        {
            index = index -1;
        }

or better still:
1
2
3
4
       iterator&operator--()
        {
            index--;
        }



Anyway, you want to call the class function getValue, right? So you need an instance of a class to call it on. The struct Iterator has never been told about any object of type IntFile. So how can it call a function on an instance of a class it knows nothing about? It needs to be told "that Intfile object over there, that's the one you're working on". if you had fifty Intfile objects, how would your Iterator know which one it is associated with?

1
2
3
4
IntFile firstIntfile;
IntFile secondIntfile;

IntFile::Iterator anIteratorObject(someFilePointer, 0); // WHICH of the above two is this meant to be working on? How is it meant to know which one to work with? 


When you create your iterator objects, they need some way of knowing which IntFile they are associated with. You could give them a pointer to the right one, or a reference to the right one.
Last edited on
not quite.
If you are in a IntFile's member function, then IntFile::getValue(index);, getValue(index); and this->getValue(index) are equivalent.
The problem is that you're coding iterator's member function. this is not an `IntFile' but an `iterator'.

¿So to which IntFile object do you want to send the getValue() message?


By the way, perhaps you could consider to open the file in IntFile's constructor and close it in its destructor.
@Repeater, I got what you mean, but correct me here if I'm wrong

I have let's say 2 IntFile objects, let's call them IntFile Obj1 and IntFile Obj2, so if I want my iterator to work with Obj1, I'd do
(IntFile::iterator i = Obj1 .begin(); i != Obj1 .end(); ++i)

and same here for Obj2
(IntFile::iterator i = Obj2.begin(); i != Obj2.end(); ++i)

Or am I wrong on that?
@ne555 I'm about to understand your words but I can't figure it out how to manage this.
Or am I wrong on that?

You are wrong on that.

With your current code, creating an IntFile::iterator like this:
(IntFile::iterator i = Obj1.begin();
gives you an IntFile::iterator identical to creating one like this:
(IntFile::iterator i = Obj2.begin();

Your IntFile::iterator object doesn't know what created it. You used a function from Obj1 to create the iterator, but that's irrelevant. Look at what IntFile::iterator knows about:

1
2
        int index = 0;
        int value = 0;


These are IntFile::iterator's member variables. This is everything an IntFile::iterator knows about the universe. It has no way of knowing it is associated with Obj1. It has no record of Obj1.

Consider if this was the IntFile::iterator's member variables:

1
2
3
        int index = 0;
        int value = 0;
        IntFile* the_Intfile_I_am_associated_with;


If you populated that pointer variable, the_Intfile_I_am_associated_with, suddenly the IntFile::iterator does know which IntFile it is associated with, and will be able to call class functions on that IntFile.

Last edited on
@Repeater, Yes, now, finally I got it. The comparison with universe was clear enough. Thanks for that.
Last edited on
@Repeater, Terribly sorry to bother you again, but that was a bit recklessly to think that if i add IntFile* the_Intfile_I_am_associated_with; then the whole thing would work so what else should I do?

But there is one more question, how should i call getValue, like that return IntFile::getValue(int index); or like that return IntFile::getValue(index);

return the_Intfile_I_am_associated_with->getValue(index);

This does rely on you making sure that the_Intfile_I_am_associated_with does actually point to the correct IntFile object. You could do it in the constructor:

1
2
3
4
5
 iterator(IntFile* the_intfile_to_associate_with, int idx)
{
the_Intfile_I_am_associated_with = the_intfile_to_associate_with;
 ...
}

called from the IntFile class function:
1
2
3
4
    iterator begin()
    {
        return iterator(this, 0);
    }


This would also mean that you'd go through the_Intfile_I_am_associated_with to access the FILE*, which is a lot more sensible. A const reference would be better than a pointer, but the important thing here is you understanding how classes work.



Last edited on
@Repeater, Thank you so much sir!!! It works, I can't express how much you helped me.
Topic archived. No new replies allowed.