C++ Operator Overload Error

Go To StackoverFlow.com

1

I'm trying to create my own version of an array called a safearray, to test my knowledge of operator overloading and creating proper class's and such.

I'm encountering two errors.

SafeArray.h:11:15: error: ‘const int SafeArray::operator’ cannot be overloaded

SafeArray.h:10:10: error: with ‘int& SafeArray::operator’

My code is split between three files.

Main.cpp

#include <cstdlib>
#include <iostream>

#include "SafeArray.h"

using namespace std;

int main(int argc, char** argv) {

    SafeArray a(10); // 10 integer elements

    for (int i = 0; i < a.length(); i++) {
        cout << i << " " << a[i] << "s" << endl; // values initialise to 0
    }

    cout << endl << a[1]; // Program exits here.

    a[3] = 42;
    cout << a[3];
    a[10] = 10;
    cout << a[10];
    a[-1] = -1; // out-of-bounds is "safe"?

    SafeArray b(20); // another array

    b = a; // array assignment

    for (int i = 0; i < b.length(); i++) {
        cout << b[i] << endl; // values copied from a
    }

    return 0;
}

SafeArray.h

#ifndef SAFEARRAY_H
#define SAFEARRAY_H

class SafeArray {
public:
    SafeArray(int);              // int variable will be the array size
    int length();
    int boundsCheck(int y);       // constructor will call this function
//    const SafeArray operator= (const SafeArray&);
    int& operator[] (int y);
    const int operator [] (const int y); // you need this one too.

    SafeArray &operator=(SafeArray rhs) { 
    std::swap(array, rhs.array);
    std::swap(length_, rhs.length_);
        }

    SafeArray(SafeArray const &other);
    ~SafeArray();
private:
    int length_;
    int *array;
    //int array[];
};

#endif  /* SAFEARRAY_H */

SafeArray.cpp

#include "SafeArray.h"
#include <iostream>

SafeArray::SafeArray(int x) {
    length_ = x;
    array = new int[length];
    for (int i = 0; i < length_; i++) {
        array[i] = 0;
    }
}

int SafeArray::length() {
    return this->length_;
}

int SafeArray::boundsCheck(int y) {

}

int& SafeArray::operator[] (int y) {
    return array[y];
}

SafeArray::~SafeArray() { 
    delete [] array;
}

SafeArray::SafeArray(SafeArray const &other) { 
    int *temp = new int[rhs.size_];
    for (int i=0; i<rhs.size_; i++)
        temp[i] = rhs.array[i];
    std::swap(temp, array);
    delete [] temp;
    return *this;
}
2012-04-03 23:40
by Sasstraliss
I don't see anywhere where you're dynamically allocating memory.. - Oliver Charlesworth 2012-04-03 23:42
So, I saw this glaring at me after a couple of seconds: int array[]; . You have declared an incomplete sized array. Perhaps your compiler takes this to mean array[0], but zero sized arrays are not standard. You then proceed to assign values to x elements in this array... which has never been initialized. I don't even see how this could compile - Ed S. 2012-04-03 23:44
Oh, yes, it will compile all right. In fact it is an idiom for when you want an array but don't know the size at compile time, so you allocate the struct dynamically to the right size and then you can use the array up to the size. What it gives you is that the data for the array is in the struct and not a separate chunk of memory elsewhere. And a certain amount of obscurity :- - DRVic 2012-04-03 23:50
It will not compile with a conforming implementation. gcc includes (at least something similar to) C99 flexible array members as an extension to C++. I'm not sure if it'll diagnose the problem in pedantic mode or not, but it might at least be worth a shot - Jerry Coffin 2012-04-04 00:07


3

Your class definition isn't valid. int array[] is an incomplete type, which must not appear as a (non-static) class member. Some compilers accept this as a synonym for int array[0], but zero-sized arrays are not valid in C++, either (only in C99).

In short, you cannot write your code the way you do. You need to learn about dynamic allocation and manage your own memory. Check out how std::vector is implemented.

In C++11, I might recommend a std::unique_ptr<int[]> array as a quick-fix approach, to be initialized as array(new int[x]).

2012-04-03 23:43
by Kerrek SB


0

Actually int array[] is valid, and may appear as a class member. The following compiles with strict C++11 conformance:

class foo 
{
public:
    foo() {}
    int length;
    int A[];
};

void ralph()
{
    foo *bar = (foo *)new int[ 21 ];
    bar->length = 20;
    bar->A[0] = 1;
}

This is legal, and has its advantages (occasionally). Although it is not commonly used.

However, I suspect that the OP wanted something more along the lines of

class SafeArray {
public:
    SafeArray(int);              // int variable will be the array size
    int length();
    int boundsCheck(int y);       // constructor will call this function

    int& operator[] (int y);
    const int operator [] (const int y) // you need this one too.
private:
    int length_;
    int *array;
};

along with

SafeArray::SafeArray(int x) {
    length_ = x;
    array = new int[length];
    for (int i = 0; i < length_; i++) {
        array[i] = 0;
    }
}
2012-04-04 00:04
by DRVic


0

As @Kerrek already pointed out, your class definition is clearly wrong (shouldn't compile).

To fix it, you want to change the definition to something like:

int *array;

Then in your default ctor you could use something like this:

SafeArray::SafeArray(unsigned size = 0) 
    : array(new int[size])
{ 
    for (unsigned i=0; i<size; i++)
        array[i] = 0;
}

Then, yes, you'll need to write an assignment operator. The usual way is called the copy and swap idiom. You create a copy, then swap the contents of the current one with those of the copy:

SafeArray &operator=(SafeArray rhs) { 
    std::swap(array, rhs.array);
    std::swap(length_, rhs.length_);
}

Along with that, you'll need a copy constructor that makes a copy of the data as well:

SafeArray::SafeArray(SafeArray const &other) { 
    int *temp = new int[rhs.size_];
    for (int i=0; i<rhs.size_; i++)
        temp[i] = rhs.array[i];
    std::swap(temp, array);
    delete [] temp;
    return *this;
}

Finally, you'll need a destructor to destroy an object and (particularly) delete the memory it holds:

SafeArray::~SafeArray() { 
    delete [] array;
}

Then realize that all of that is an ugly mess that will never really work well. In particular, the basic methodology is restricted to an array that's basically fixed in size. As long as you only store ints, it's fairly easy to overlook the problems, and make a dynamic array that (sort of) works. When/if you want to store some other type, however, you just about need to separate allocating memory from initializing objects in that memory, which means throwing away essentially all the code above, and replacing it with something that:

  1. keeps track of the array size and allocation size separately
  2. allocates memory with ::operator new, an Allocator object, or something else similar
  3. uses placement new to initialize objects in the memory when needed.
  4. uses explicit destructor calls to destroy the objects
  5. uses ::operator delete to release memory

and so on. To summarize, std::vector is not a trivial piece of work.

2012-04-04 00:05
by Jerry Coffin


0

The error message refers to these two lines:

int& operator[] (int y);
const int operator [] (const int y); // you need this one too.

Your error message says that (int y) and (const int y) are too similar to be two different overloads of the [] operator. You cannot overload on (int y) and (const int y) because the calls would all be ambiguous.

You probably meant to return a const int if your SafeArray is const, but return an int& if your SafeArray is not const. In that case, you declare the second function to apply to const SafeArray, by putting the word const after the parameter list. This is what you should write in SafeArray.h:

int& operator[] (int y);
const int operator [] (int y) const; // you need this one too.

You would then have to write both of these functions in SafeArray.cpp:

int& SafeArray::operator[] (int y) {
    return array[y];
}

const int SafeArray::operator[] (int y) const { // you need this one too.
    return array[y];
}
2014-11-14 22:37
by Null Pointers etc.