views:

342

answers:

5
+4  Q: 

operator[][] C++

I'd like to overload operator[][] to give internal access to a 2D array of char in C++.

Right now I'm only overloading operator[], which goes something like

class Object
{
    char ** charMap ;
    char* operator[]( int row )
    {
        return charMap[row] ;
    }
} ;

It works ok.. Is it possible to override operator[][] though?

+4  A: 

There is no operator[][]. Evaluating a[x][y] first calls operator[] on a, and then operator[] again on the result of that.

So the operator[] of you object has to return another object with its own operator[], which then will access the requested value.

sth
+1  A: 

As far as I know there is no such thing as operator[][]. What you can do is you could return from your operator[] method something that has overloaded operator[].

Actually you are doing it now, because you return char* which can be indexed using [] again.

pajton
+16  A: 

There is no operator [][]: that's two [] operations in a row. You could:

  • Have Object::operator[] return an object of a second class representing a row, which has its own operator[] method that takes a column number;
  • Write a get(int row, int column) method and use that instead of operator overloading. I'd recommend this unless your object absolutely has to behave like an array.
rjh
+1 If your class is not intended to behave like a function, leave operator() alone.
Pete Kirkham
+10  A: 

Don’t try to do that – as others have said, overloading operator [] the way you do actually provides the [][] syntax for free. But that’s not a good thing.

On the contrary – it destroys the encapsulation and information hiding of your class by turning an implementation detail – the char* pointer – to the outside. In general, this is not advisable.

A better method would be to implement an operator [,] which takes more than one argument, or indeed an operator [][]. But neither exists in C++.

So the usual way of doing this is to ditch operator [] altogether for more than one dimension. The clean alternative is to use operator () instead because that operator can have more than one argument:

class Object
{
    char ** charMap ;
    char& operator ()(int row, int column)
    {
        return charMap[row][column];
    }
};

For more information, see the article in the C++ FAQ Lite.

Konrad Rudolph
+1 for suggesting `operator()`
missingfaktor
Your answer raises some good points, but supporting operator[] doesn't need to destroy encapsulation -- instead of returning a pointer, you can return a proxy object that supports operator[] without exposing any internals.
Jerry Coffin
@Jerry: true but then the proxy object is vastly more work and any benefit is doubtful for a multi-dimensional object (of course, for a *jagged* array, it makes perfect sense).
Konrad Rudolph
This is a __good__ answer!
bobobobo
@Konrad: The proxy *is* more work, but I think "vastly" overstates it a bit -- the proxy is about a half dozen lines of code (though for N dimensions, you need N-1 proxy classes, so for more than a 3D or so, you generally want to write a template).
Jerry Coffin
A: 

There is no [][] operator. What actually happens is that the second [] operates on the variable returned by the first []. Because there is already that functionality, it would create ambiguity were there to exist a [][] operator.


For example: let's say you have a variable x of some type T.

T x = new T();

If we use the [] operator, let's say a variable of other type Q is returned:

Q y = x[0];

And then using the [] operator on a variable of type Q might return a variable of type R:

R z = y[0];

Therefore x[][] returns a variable of t ype R.

Let's say we actually were able to overload [][] for type T such that it returned a type S:

S a = x[0][0];

The compiler would have no way of knowing if it should use the [][] operator on x to return a type S variable, or use the [] operator twice in a row to return a type R variable. This is the ambiguity I mentioned above.


Your best bet if you're stuck on using square brackets is to have operator[] return a variable which also has [] overloaded (or perhaps a variable of the same type, with a flag set), and have that initially returned variable deal with the second [].

But the best solution here (as mentioned already in another answer) is to use a different operator such as ().

Cam
The ambiguity could be easily resolved, e.g. by using a greedy parsing. Also, your first code contains an error since `new` returns a *pointer*.
Konrad Rudolph