Calling overloaded operator from class

Hello all!

I have a simple class of Vector (just doing it for learning purposes) and I have overloaded the [] operator:
1
2
3
4
5
6
7
double& Vector::operator[](int i)
{
        std::cout << "lol\n";
	assert(i > -1);
	assert(i < mSize);
	return mData[i];
}


Now, this works perfectly fine. I also have a read() method:
1
2
3
4
double& Vector::Read(int i) const
{
	return mData[i];
}


Now, the problem is: when I do:
vector v;
std::cout << v.Read(2)

I will not see the "lol" message. So my Read() method is not using the overloaded operator [] apparently. How do I make it use it? I was thinking about doing something like:

1
2
3
4
double& Vector::Read(int i) const
{
	return this->operator[](i);
}


but obviously it doesn't even compile.

Thanks for your time :)
Jeremy.
Is mData of type Vector or is it a double* pointer to a new-ed array of doubles? If so, it will be the regular operator[] that is invoked on mData, not your overload (this only works with variables of your type Vector.)

You could force Read to call the operator[] member using const_cast<>...

1
2
3
4
5
6
7
8
// return a double not a double&, as don't want caller to
// be able to change vector; this is a const method!
// (could return a const double& but that's prob overkill
// for a type that small.)
double Vector::Read(int i) const
{
	return const_cast<Vector*>(this)->operator[](i);
}


Should avoid using const_cast<> if at all possible, but here it's benign as you know you're not allowing the caller to change anything (Read is a const method) as long as you don't return a non-const ref to the element.

The correct solution, however, is to do what std::vector does and provide two overloads for each type.

1
2
reference operator[] (size_type n);
const_reference operator[] (size_type n) const;

http://www.cplusplus.com/reference/vector/vector/operator%5B%5D/

e.g.

Your existing double& Vector::operator[](int i) plus

1
2
3
4
5
6
7
8
// for smaller types can use type rather than const type& for return
double Vector::operator[](int i) const
{
        std::cout << "const lol\n";
	assert(i > -1);
	assert(i < mSize);
	return mData[i];
}


Andy

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
#include <iostream>
#include <algorithm> // for fill_n
#include <cassert>
using namespace std;

#define INC_CONST_ARRAY_SUBSCR_OP

class Vector
{
private:
    static const int mMaxSize = 16; // for quick text
    int mSize;
    double mData[mMaxSize];

public:
    Vector() : mSize(0)
    {
        fill_n(mData, mMaxSize, 0.0);
    }

    void PushBack(double d)
    {
        assert(mSize < mMaxSize);
        mData[mSize++] = d;
    }

    double Vector::Read(int i) const;
    double& Vector::operator[](int i);
#ifdef INC_CONST_ARRAY_SUBSCR_OP
    double Vector::operator[](int i) const;
#endif
};

double& Vector::operator[](int i)
{
    std::cout << "lol\n";
    assert(i > -1);
    assert(i < mSize);
    return mData[i];
}

#ifdef INC_CONST_ARRAY_SUBSCR_OP
// return double not double&
double Vector::operator[](int i) const
{
    std::cout << "const lol\n";
    assert(i > -1);
    assert(i < mSize);
    return mData[i];
}
#endif

// return a double not a double&, as don't want caller to
// be able to change vector; this is a const method!
// (could return a const double& but that's prob overkill
// for a type that small.)
#ifdef INC_CONST_ARRAY_SUBSCR_OP
double Vector::Read(int i) const
{
    return this->operator[](i);
}
#else
/double Vector::Read(int i) const
{
    return const_cast<Vector*>(this)->operator[](i);
}
#endif

int main() {
    Vector v;
    v.PushBack(1.0);
    v.PushBack(2.0);
    v.PushBack(3.0);

    cout << "v[1] = " << v[1] << "\n";
    cout << "v.read(0) = " << v.Read(0) << "\n";

    return 0;
}

Last edited on
Thanks a lot Andy! Now I understand everything :)

There is another problem I have related with this class, but since it is totally different, I wrote another topic for it. Hope it's fine.

EDIT: since I am having errors posting another topic, here is the second problem I have:

Hello :)

I have the following problem. There is a class Vector I wrote myself for learning purposes. In this class, I have overloaded the << operator. The code for this is:

1
2
3
4
5
6
7
8
9
10
std::ostream& operator<<(std::ostream& output,const Vector& v)
{
        output << "(";
        for(int i=0 ; i<v.GetSize() ; i++)
        {
                output << v(i) << ", ";
        }
        std::cout << ")";
        return output;
}


This works perfectly fine. If I have a Vector named "jci" that consists of 3 zeros, then by typing:

std::cout << jci

I will obviously receive:
(0, 0, 0)

which is fine. But what if I would like to receive:

jci = (0,0,0)

How do I tell my overloaded function how did the programmer name the instance of the class? That in my main file I typed "Vector jci"? Apart from the obvious solution - adding the name of the instance as a member of the class?
Last edited on
AFAIK C++ can't really do that.
I can think of a macro
1
2
3
4
5
6
7
8
9
10
#define NAMED_COUT(symbol) (std::cout << #symbol " = " << symbol)

#include <iostream>

int main()
{
    int number = 42;
    NAMED_COUT(number);
    return 0;
}


You can try googling something like "c++ reflection variable".
Last edited on
Nope -- C++ does not remember variable names. The names is source code are just for programmers; by the time an executable has been built the variables are just memory addresses.

What's wrong with writing

std::cout << "jci = " << jci << "\n";


Quite often, what you want to display to a user is different to the variable name. e.g.

std::cout << "Blood Pressure = " << BP << "\n";


Andy

PS The compiler/linker can create a debug symbol table which allows the a debugger to work out the variable name by mapping ite memory address to name. But that's not for general use in a program; just for debugging. And if you're talking about optimized code (release build), it's quite possible that some variables have been eliminated by the compiler.
Last edited on
Topic archived. No new replies allowed.