Unable to decipher "error: expected unqualified-id before 'int'" - c++

I've been looking around and haven't come up with any tangible solutions. It sounds like it is looking for a default constructor instead of the one in place but I have one below. Moving it up as the first listed constructor didn't change the error messages so I'm wrong about that. Here's the full error message (using jGRASP):
In file included from intset.h:47:0,
from IntSet.cpp:1:
IntSet.cpp:12:11: error: expected unqualified-id before 'int'
IntSet(int a, int b, int c, int d, int e) {
^
IntSet.cpp:12:11: error: expected ')' before 'int'
Here's the IntSet.cpp code:
#include "intset.h"
//#include <algorithm>
//#include <iostream>
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
//Constructors
IntSet(int a, int b, int c, int d, int e) {
size = a;
if(b > size) {
size = b;
}
if(c > size) {
size = c;
}
if(d > size) {
size = d;
}
if(e > size) {
size = e;
}
set = new bool[size];
for(int i = 0; i <= size; i++) {
if(i == a || i == b || i == c || i == d || i == e) {
insert(i);
} else {
remove(i);
}
}
}
IntSet(int a, int b, int c, int d) {
IntSet(a, b, c, d, -1);
}
IntSet(int a, int b, int c) {
IntSet(a, b, c, -1, -1);
}
IntSet(int a, int b) {
IntSet(a, b, -1, -1, -1);
}
IntSet(int a) {
IntSet(a, -1, -1, -1, -1);
}
//Copy constructor
IntSet(const IntSet& x) {
size = x.size;
for (int i = 0; i <= x.size; i++ ) {
set[i] = x.set[i];
}
}
//Destructor
~IntSet()
{
//for(int i = this.length(); i >= 0; i--) {
// this[i]
//}
}
////////////////////////
bool insert(int a) {
if(a <= size && a >= 0) {
set[a] = true;
return true;
}
else if(a >= 0) {
//removed "new" from line below
IntSet temp = IntSet(a);
&this += temp;
set[a] = true;
return true;
}
return false;
}
bool remove (int a) {
if (isInSet(a)) {
set[a] = false;
return true;
}
return false;
}
bool isEmpty() {
bool retVal = true;
for (int i = 0; i <= size; i++) {
if (set[i] == true) {
retVal = false;
}
}
return retVal;
}
bool isInSet (int a) {
if (set[a]){
return true;
}
return false;
}
/////////////////////////////////////////////
IntSet operator + (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] || a.set[i]){
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator * (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] && a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator - (IntSet a) {
IntSet c = IntSet();
c.size = 0;
for (int i = 0; i <= size; i++) {
if (set[i] && !a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
c.size++;
}
return c;
}
IntSet operator = (const IntSet a) {
return IntSet(a);
}
IntSet operator += (IntSet a) {
return IntSet(operator+(a));
}
IntSet operator *= (IntSet a) {
return IntSet(operator * (a));
}
IntSet operator -= (IntSet a) {
return IntSet(operator - (a));
}
IntSet operator == (const IntSet a) const{
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return false;
}
}
return true;
}
IntSet operator != (IntSet a) {
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return true;
}
}
return false;
}
IntSet operator << (IntSet a) {
cout << "{";
for(int i = 0; i < size; i++) {
if(set[i]) {
cout << " " << i;
}
}
cout << "}";
}
IntSet operator >> (IntSet a) {
int index;
while(cin >> index && index != SENTINEL) {
insert(index);
}
}
Here is the attached intset.h code:
#ifndef INTSET_H
#define INTSET_H
#include <iostream>
#include <algorithm>
using namespace std;
class IntSet {
public:
//Constructors
IntSet();
IntSet(int);
IntSet(int, int);
IntSet(int, int, int);
IntSet(int, int, int, int);
IntSet(int, int, int, int, int);
IntSet(const IntSet&); // M: Added the &; must be a pointer or reference
~IntSet();
//Overloaded Operators M: Added 'IntSet' in front of the word 'operator.'
// It was required syntax.
IntSet operator+(IntSet);
IntSet operator*(IntSet);
IntSet operator-(IntSet);
IntSet operator=(IntSet);
IntSet operator+=(IntSet);
IntSet operator*=(IntSet);
IntSet operator-=(IntSet);
IntSet operator==(IntSet);
IntSet operator!=(IntSet);
IntSet operator<<(IntSet);
IntSet operator>>(IntSet);
//Functions
bool insert(int);
bool remove(int);
bool isEmpty();
bool isInSet(int);
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
#include "IntSet.cpp"
#endif
I haven't had much experience with header files so it wouldn't surprise me if I formatted something incorrectly but I'm looking at plenty of other samples provided by the professor and there isn't anything unusual about mine. I thought maybe it had something to do with the order listed in the .h file and that I wasn't following the same exact order in the .cpp but nothing changed when I had everything listed in the same order.

There is a lot that is wrong with your code. We are going to have to jump around a bit between the header and the implementation. Ready?
In your header you do this:
class IntSet {
/* stuff */
private:
bool set[];
};
First of all, the name set is a bad choice: it is the name of a class in namespace stdw which you are importing by having using namespace std in your header file. This can be confusing at best.
More importantly, the syntax bool set[] isn't correct in this context. Even if your compiler allows it, it's an extension. Who knows what it does and how it will behave on other compilers? Avoid it.
If you want to declare an array, declare an array. If you want to declare a pointer, declare a pointer. Just remember: an array isn't a pointer.
Unfortunately you don't, becase later on in your code you do this:
set = new bool[size];
What is this supposed to do? set isn't a pointer, it's some kind of array, and you cannot assign a pointer to an array.
Now, we get to the second problem: you declare some member variables for your class, in your header file:
class IntSet {
/* some stuff here */
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
Then in your implementation you have the following code floating up at the top:
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
I don't think that this does what you think it does. It seems that your intention is to initialize those variables, but that's not what happens. Remember, those variables only exist as members variables that belong to a particular instance of a class, and they are not "free-standing". So what's happening here?
Well, this declares all these variables again, so you have variables called MAXSIZE, size, set and SENTINEL that are valid anywhere in that translation unit (i.e. the .cpp file), independent of the member variables in the class.
This, of course, means that the member variables with those names aren't initialized (well, except set which you assign a pointer to, which we already know is wrong). This will cause your code to exhibit undefined behavior. After all, the value of an uninitialized variable can be anything at all.
If your intention had been to initialize the class members, then you should remove that code and initialize those variables in your constructor(s):
IntSet::IntSet(int a, int b, int c, int d, int e)
: size(a), MAXSIZE(25000), SENTINEL(-1)
{
/* whatever*/
}
Notice, by the way, how I used IntSet:: in front of the constructor name? This is called the scope resolution operator. Remember, there is no constructor called IntSet. The constructor belongs to a class, which is called IntSet, and outside of that class, it's proper name is IntSet::IntSet. A small example may help:
class Test
{
int Length;
public:
/* notice how inside the class, you only need Test
* when providing a body for the constructor. This
* makes sense. You know which class you inside of.
*/
Test()
: Length(0)
{
}
Test(int len);
};
/* Now we are outside the class. We need to help
* the compiler out and tell it what class the
* function belongs to.
*/
Test::Test(int len)
: Length(len)
{
}
A tangential point as to do with the names that you are using. What's a? Why do you use a to initialize something called size? You should choose meaningful variables names that help document the code so that when you have to read it back your head doesn't explode.
Another tangential point is that if variables like MAXSIZE and SENTINEL are going to be shared between all instances of the class, then, for future reference, you should probably consider making them static class members.
Lastly, you have this bit of code in your header file
#include "IntSet.cpp"
This is, almost certainly, not correct. You should never do this (there may be some who think that there are exceptions, but don't learn bad habits at this point. When you know enough to stumble on this legitimately, then you will know enough to determine whether it's the right thing to do or not).
What makes it worse is that your implementation file contains:
#include "IntSet.h"
Think about what you are doing here: when the compiler is processing the file IntSet.h you are telling to also process the file IntSet.cpp. The file IntSet.cpp tells the compiler to process the file IntSet.h. Which tells the compiler to process the file IntSet.cpp. And so on and so forth.
Generally speaking, implementation files (.cpp) will include header files. Header files will only include other header files.
There are a few other issues, but you should probably fix all these things, and then, if you are still having issues, post a new question and we can go from there.
Good luck!

You need to put the name of the class and :: before defining a member function.
IntSet::IntSet(int a, int b, int c, int d, int e) {
//^^^^^^^^
//here
Do the same with the other constructors, the operators and methods.

Related

Problems with two-dimensional vector in c++

I'm trying to write a class in c++, that presents a group of people (each person has its own row), and the numbers in the rows represent this person's friends. If person a is person's b friend, then the person b is person's b friend as well.
I came up with something like this:
class Friends {
public:
Friends(int n);
// Creates a set of n people, no one knows each other.
bool knows(int a, int b);
// returns true if the 2 people know each other
void getToKnow(int a, int b);
// Person a & b meet.
void mutualFriends(int a, int b);
// cout's the mutual friends of person a & b
void meeting(int a);
//all friends of person a also become friends
int max();
//return the person with the highest number of friends
private:
vector<vector<int>> friends;
};
Friends::Friends(int n) {
vector<vector<int>> friends;
}
bool Friends::knows(int a, int b) {
for(int i=0; i<friends[a].size(); i++) {
if (friends[a][i]==b) {
return true;
}
}
return false;
}
void Friends::getToKnow(int a, int b) {
friends[a].push_back(b);
friends[b].push_back(a);
}
void Friends::mutualFriends(int a, int b) {
for (int i=0; i<friends[a].size(); i++) {
for (int j=0; j<friends[b].size(); j++) {
if (friends[a][i]==friends[b][j])
cout << friends[a][i] <<", ";
}
}
}
void Friends::meeting(int a) {
for (int i=0; i<friends[a].size(); i++) {
for(int j=0; j<friends[a].size();j++) {
if(i!=j && i!=a && j!=a) {
getToKnow(i,j);
}
}
}
}
int Friends::max() {
int maks = 0;
for (int i=0; i<friends[i].size(); i++) {
if (friends[i].size()<friends[i+1].size())
maks = i;
}
return maks;
}
int main() {
Friends f1 (4);
f1.getToKnow(1,3);
}
So far, every time I try to add something to the vector (f.e. with the function getToKnow) the compiler can't compile the program, pointing that
friends[a].push_back(b);
friends[b].push_back(a);
is wrong. The exact information displayed is "Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)". I don't know what I'm doing wrong and if I'm using the 2d vector correctly.
In the line
Friends::Friends(int n) {
vector<vector<int>> friends;
}
you are creating a local vector of vectors which will be deallocated upon leaving the function.
What you are looking for is:
Friends::Friends(int n) {
friends.resize(n);
}
Which will allocate n vectors, allowing you to access any element below that threshold.
I'm just guessing here, but you should probably create a constructor initialize list to set the size of the member variable:
Friends::Friends(int n)
: friends(n)
{
// Empty
}

Why am I getting a Link error when I try to overload an operator?

I'm doing a project exercise, where I'm revising a previous project of a class I created called Polynomial to use a link list (the original used arrays). The link list uses a template so that any type can be passed into it.
One of the problems I ran into with this project exercise is that I am trying to pass an object of type PolyNumber (from a class I made), and the link list bag I made has a function that compares any item (using ==) that is passed to it.
It works fine with regular types, such as int and string, but runs into problems with custom made object types. So I figured out how to overload the == operator in the PolyNumber class. By itself, it works when I test this class, but when I use this type with the Polynomial class with the Link List implementation, I get errors such as the following for each method in the Polynomial class:
Error LNK2005 "public: __thiscall PolyNumber::PolyNumber(int,int)" (??0PolyNumber##QAE#HH#Z) already defined in Polynomial.obj Project11
Here's my code for those files, but as you can see in the code, there are other files that go with this code, such as the LinkedBag for the link list object, but for space I just include these:
PolyNumber.h
#pragma once
class PolyNumber
{
public:
PolyNumber();
PolyNumber(int set_coefficent, int set_degree);
void setDegree(int set);
void setCoefficient(int set);
int getDegree();
int getCoefficient();
friend bool operator== (const PolyNumber& p1, const PolyNumber& p2);
friend bool operator!= (const PolyNumber& p1, const PolyNumber& p2);
private:
int degree;
int coefficient;
};
PolyNumber.cpp
#include "PolyNumber.h"
PolyNumber::PolyNumber()
{
coefficient = 0;
degree = 0;
}
PolyNumber::PolyNumber(int set_coefficent, int set_degree)
{
coefficient = set_coefficent;
degree = set_degree;
}
void PolyNumber::setDegree(int set)
{
degree = set;
}
void PolyNumber::setCoefficient(int set)
{
coefficient = set;
}
inline int PolyNumber::getDegree()
{
return degree;
}
inline int PolyNumber::getCoefficient()
{
return coefficient;
}
bool operator== (const PolyNumber& p1, const PolyNumber& p2)
{
return (p1.coefficient == p2.coefficient && p1.degree == p2.degree);
}
bool operator!= (const PolyNumber& p1, const PolyNumber& p2)
{
return !(p1 == p2);
}
Polynomial.h
#pragma once
#include "PolynomialInterface.h"
#include "LinkedBag.cpp"
#include "PolyNumber.cpp"
static const int POLYNOMIAL_SIZE = 10;
class Polynomial : public Polynomoal_Interface
{
public:
//Cunstructs am empty Polynomial
Polynomial();
//Copy constructor
Polynomial(Polynomial& copy);
/** Cunstructs a Polynomial with a client defined Polynomial
#param an array of non-negative integer coeffient that does not exceed POLYNOMIAL_SIZE, each coeffient in the array has a power that correspounds
to the respective value of the location of the ceffient in that array. */
Polynomial(int coeffient[POLYNOMIAL_SIZE], int size);
int degree();
int coefficient(int power);
bool changeCoefficient(int newCoefficient, int power);
private:
//static const int POLYNOMIAL_SIZE = 10;
//int polynomial[POLYNOMIAL_SIZE];
LinkedBag<PolyNumber> bag;
};
Polynomial.cpp
#include "Polynomial.h"
Polynomial::Polynomial()
{
}
Polynomial::Polynomial(Polynomial& copy)
{
std::vector<PolyNumber> copyFrom = copy.bag.toVector();
for (int i = 0; i < copyFrom.size(); i++)
{
bag.add(copyFrom[i]);
}
}
Polynomial::Polynomial(int coeffient[POLYNOMIAL_SIZE], int size)
{
for (int i = 0; i <= size; i++)
{
PolyNumber number = { coeffient[i], i + 1 };
bag.add(number);
}
}
int Polynomial::degree()
{
int max = 0;
std::vector<PolyNumber> result = bag.toVector();
for (int i = 0; i < result.size(); i++)
{
if (result[i].getDegree() > max)
{
max = result[i].getDegree();
}
}
return max;
}
int Polynomial::coefficient(int power)
{
int result = 0;
std::vector<PolyNumber> powerOf = bag.toVector();
for (int i = 0; i < powerOf.size(); i++)
{
if (powerOf[i].getDegree() == power)
{
result = powerOf[i].getCoefficient();
}
}
return result;
}
bool Polynomial::changeCoefficient(int newCoefficient, int power)
{
PolyNumber number = { newCoefficient, power };
int result = coefficient(power) + newCoefficient;
bag.remove(number);
number.setCoefficient(result);
bag.add(number);
return true;
}
You have #include "PolyNumber.cpp" instead of #include "PolyNumber.h".
That makes all the methods defined in PolyNumber.cpp to be included (and re-defined) in Polynomial.cpp.
The same will happen with LinkedBag.
Why are you including cpps?

C++ Array variable in class causes "was not declared in this scope" error in one function of implementation file but not in the constructor

The title pretty much says it all. I'm required to write a program for a Software course I'm taking that puts two basic algorithms against each other in a game of checkers. For this, I have a Square class that stores whether the square is occupied (bool), which player by (enum Pl, either NA, P1, or P2), and the label of that square (Index, int). I then created a Board class, which is effectively a 2D array of Squares that will have dimensions specified by the user. However, in the implementation file of my Board class, I'm having an error using the board[][] array in one of my functions. I get the error "board was not declared in this scope", which shouldn't be too tricky to figure out, except that the exact same syntax (at least from what I can see, and I've been working on fixing this for a while now) that's causing the error works perfectly in the constructor for the Board class in the same file. Below is the code for my Board.h file, and the relevant parts of my Board.cpp file:
Board.h:
#ifndef BOARD_H
#define BOARD_H
#include "Square.h"
#include <string>
class Board
{
public:
Board(int);
int getBsize();
int getWinner();
std::string getCmove();
Square getSquare(int, int);
void setWinner(int);
void setCmove(std::string);
bool canMoveL(int, int);
bool canMoveR(int, int);
bool canTakeL(int, int);
bool canTakeR(int, int);
void P1Move(int, int);
void P2Move(int, int);
void printCmove(std::string);
void printWin(std::string);
private:
Square board[12][12];
int bSize;
int winner;
std::string cMove;
};
#endif // BOARD_H
Board.cpp constructor as well as top of the file (in case the error is with the libraries and files I've included in Board.cpp):
#include "Square.h"
#include "Board.h"
#include <string>
Board::Board(int bSize)
{
Board::bSize = bSize;
Board::winner = 0;
Board::cMove = "";
Board::board[12][12];
int x = bSize-1;
int index = 1;
for(int j = 0; j < bSize; j++)
{
for(int i = 0; i < bSize; i++)
{
if(((i%2!=0)&&(j%2==0))||((i%2==0)&&(j%2!=0)))
{
if((j==x/2)||(j==x/2+1))
{
board[i][j] = Square(false, NA, index);
index++;
}
else if(j < x/2)
{
board[i][j] = Square(true, P1, index);
index++;
}
else if(j > x/2+1)
{
board[i][j] = Square(true, P2, index);
index++;
}
}
else
{
board[i][j] = Square(false, NA, 0);
}
}
}
}
Function in Board.cpp causing the error:
bool canMoveL(int i, int j)
{
bool temp = false;
Square sq = board[i][j];
if((i-1 < 0)||((sq.getPl() == P1)&&(j-1 >= bSize))||((sq.getPl() == P2)&&(j-1 < 0)))
{
return temp;
}
if(sq.getOcc() == 0)
{
return temp;
}
else
{
if(sq.getPl() == P1)
{
temp = true;
}
else if(sq.getPl() == P2)
{
temp = true;
}
}
return temp;
}
Note: Since I haven't been able to test the canMovL function, I realise there may be errors in that as well, but I'm specifically just looking for help fixing the error I get with the board array in canMovL(). Thanks.
bool canMoveL(int i, int j)
should be
bool Board::canMoveL(int i, int j).
else you define free function unrelated to Board.

c++ Copy constructors and destructors

I am learning constructors and Destructors in c++; Help me grasp my mistakes even if they are silly...
HERE is a code I have written to perform addition using classes in c++; This creates two summands of datatype num and employs the constructor sum() to perform sum of the two numbers; However when everything was goin' alright, I stumbled upon creating a copy constructor for num , (Although not necessary but still for practice)... without the dynamic object of the class sum it is not possible to run the code anyway(without removing the copy constructor)... Help me improve my code and my mistakes in the code below; Also I wanna know how to make use of the copy constructor in this program; the problem being that in the destructor the delete operation is being performed multiple times on the same piece of memory (I suppose)
Here's my Code
#include<iostream>
#include<new>
using namespace std;
class num
{
public:
int *a;
num(int x)
{
try
{
a=new int;
}
catch(bad_alloc xa)
{
cout<<"1";
exit(1);
}
*a=x;
}
num(){ }
num(const num &ob)
{
try
{
a=new int;
}
catch(bad_alloc xa)
{
cout<<"1''";
exit(2);
}
*a=*(ob.a);
}
~num()
{
cout<<"Destruct!!!";
delete a;
}
};
class sum:public num
{
public:
int add;
sum(num n1,num n2)
{
add=*(n1.a)+*(n2.a);
}
int getsum()
{
return add;
}
};
int main()
{
num x=58;
num y=82;
sum *s=new sum(x,y);
cout<<s->getsum();
delete s;
return 0;
}
I may miss something - didn't use new/delete for too long, but tried to correct all what I noticed.
P.S. always use smart pointers.
#include <iostream>
#include <exception>
#include <new>
using namespace std;
int* allocate(const char* err_msg, int exit_code)
{
int* a = nullptr;
try
{
a = new int;
}
catch (bad_alloc&)
{
cout << err_msg << endl;
exit(exit_code);
}
return a;
}
class num
{
int* a = nullptr; // always should be initialized here
public:
num() noexcept : a(nullptr) // or here
{}
/*explicit*/ num(int x) : a(allocate("1", 1))
{
*a = x;
}
num(const num& ob) : a(allocate("1''", 2))
{
*a = *(ob.a);
}
// rule of zero/three/five
// default copy assignment will copy pointer and one int will be leaked and one will be deleted twice
num& operator =(const num& ob)
{
if (&ob == this)
{
return *this;
}
*a = *(ob.a);
return *this;
}
~num()
{
cout << "Destruct!!!";
delete a;
a = nullptr; // usefull for debug
}
int value() const
{
if (a == nullptr)
{
throw runtime_error("a == nullptr");
}
return *a;
}
};
class sum
{
int add = 0;
public:
sum(const num& n1, const num& n2)
{
add = n1.value() + n2.value();
}
int getsum() const
{
return add;
}
};
int main()
{
const num x = 58;
const num y = 82;
const sum* s = new sum(x, y);
cout << s->getsum() << endl;
delete s;
return 0;
}

Assign value using overloaded subscript operator

I am trying to create custom array indexed from 1 using subscript operator. Getting value works fine, but I have no clue, why assign using subscript operator doesn't work.
class CEntry {
public:
CKey key;
CValue val;
CEntry(const CKey& key, const CValue& val) {
this->key = key;
this->val = val;
}
CEntry& operator= (const CEntry& b) {
*this = b;
return *this;
};
};
...
class EntriesArray {
public:
CEntry **entries;
int length;
EntriesArray(int length) {
this->length = length;
entries = new CEntry*[length];
int i;
for (i = 0; i < length + 1; i++) {
entries[i] = NULL;
}
};
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return *entries[index - 1];
};
};
Constructs array this way
EntriesArray a(5);
This works
a.entries[0] = new CEntry(CKey(1), CValue(1));
cout << a[1].val.value << endl;
This doesn't work
a[1] = new CEntry(CKey(1), CValue(1));
EDIT:
Using
CEntry *operator=( CEntry *orig)
it compiles okey, but gdb stops at
No memory available to program now: unsafe to call malloc warning: Unable to restore previously selected frame
with backtrace
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5f3ffff8
0x00000001000013c8 in CEntry::operator= (this=0x0, orig=0x1001008d0) at /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp:20
20 /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp: No such file or directory.
in /Users/seal/Desktop/efa du2_pokus2/efa du2_pokus2/main.cpp
At first... This:
CEntry& operator= (const CEntry& b) {
*this = b;
return *this;
};
Shouldn't work (this should result in recursive call of operator=).
The second thing is that you're trying to assign CEntry * to CEntry, this would work if you had CEntry *operator=( CEntry *orig), but I think this is bad coding practice.
This question may be related to this one.
I tried to fix your code; I believe that this is what you were trying to do:
(tested this code on g++ 5.3.0)
#include <iostream>
#include <stdexcept>
#include <string>
// Some implementation for CKey and CValue:
typedef int CKey;
struct CValue {
int value;
CValue(int value=0) : value(value) {}
};
class CEntry {
public:
CKey key;
CValue val;
CEntry(): key(0), val(0) {}
CEntry(const CKey& key, const CValue& val): key(key), val(val) {}
CEntry& operator= (const CEntry& b) {
this->key = b.key;
this->val = b.val;
return *this;
};
};
class EntriesArray {
public:
CEntry *entries;
int length;
EntriesArray(int length) {
this->length = length;
entries = new CEntry[length];
};
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw std::domain_error("out of bounds!");
}
return entries[index - 1];
};
};
int main(int argc, char* argv[]) {
using namespace std;
EntriesArray a(5);
// This works
a.entries[0] = CEntry(CKey(1), CValue(1));
cout << a[1].val.value << endl;
// This doesn't work
a[1] = CEntry(CKey(2), CValue(2));
cout << a[1].val.value << endl;
}
Also you might want to use a[1] as a[1].val.value e.g.:
cout << a[1] << endl;
To do this just add to this line to cEntry:
operator int() { return val.value; }
I hope it helps.
You could try replacing
CEntry& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return *entries[index - 1];
};
with
void Add(const int index, CEntry *pEntry) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
entries[index - 1] = pEntry;
};
but since you are now storing references to objects allocated on the heap (with new) you will need a destructor ~EntriesArray() to delete them all.
Because EntriesArray::operator[] returns a CEntry &, but new CEntry returns a CEntry *.
Perhaps you want a[1] = CEntry(CKey(1), CValue(1))? (no new.)
By the way, your current definition of CEntry::operator= will lead to a stack overflow.
This
return *entries[index - 1];
dereferences a NULL pointer.
You want the pointer itself to be overwritten by a[1] = new CEntry(CKey(1), CValue(1));, not the pointed-to-value.
Try this:
class EntriesArray
{
public:
int length;
CEntry **entries;
EntriesArray( int length ) : length(length), entries(new CEntry*[length]())
{
}
// defaulted special member functions are inappropriate for this class
EntriesArray( const EntriesArray& ); // need custom copy-constructor
~EntriesArray(); // need custom destructor
EntriesArray& operator=(const EntriesArray&); // need custom assignment-operator
CEntry*& operator[] (const int index) {
if (index < 1 || index > length) {
throw ArrayOutOfBounds();
}
return entries[index - 1];
}
};
Further to my comment above:
To make it work with writing new values, you probably need something like this
(I haven't double checked for off by one or ptr vs reference stuff)
CEntry& operator[] (const int index) {
if (index < 1) {
throw ArrayOutOfBounds();
}
// Add default elements between the current end of the list and the
// non existent entry we just selected.
//
for(int i = length; i < index; i++)
{
// BUG is here.
// We don't actually know how "entries" was allocated, so we can't
// assume we can just add to it.
// We'd need to try to resize entries before coming into this loop.
// (anyone remember realloc()? ;-)
entries[i] = new CEntry();
}
return *entries[index - 1];
};