I'm a CS student taking an OOP course and I don't know how to fix this issue. I understand that when the += operator tries to add the first element into the array, 'this' is nullptr and an exception is thrown, but I don't know how to fix it.
Shopping list header looks like this:
#include "Groceries.h"
class ShoppingList{
Groceries* list;
int size = 0, capacity = 2;
public:
//methods
ShoppingList& operator+=( const Groceries& c);
operator+= looks like:
ShoppingList& ShoppingList::operator+=( const Groceries& c) {
if (size == capacity) {
Groceries* l1 = new Groceries[capacity * 2];
l1 = list;
list = l1;
capacity *= 2;
}
list[size++]=c;//here is the exception
return *this;
}
Groceries header looks like:
#include <string>
#include <iostream>
class Groceries {
std::string product;
int quantity;
public:
Groceries() : product("empty"), quantity(0) {};
Groceries(std::string s, int x) : product(s), quantity(x) {};
Groceries(const Groceries& c);
~Groceries() {};
std::string product();
int quantity();
void Print();
};
and main HAS TO look like
int main()
{
ShoppingList L;
(L += Groceries("bread", 5)) += Groceries("cheese", 2);
L.Print();
//...
}
These statements in the body of the operator
l1 = list;
list = l1;
do not make sense. After the first assignment statement there is a memory leak because the address of the allocated memory is lost. In fact these two statements are equivalent to this statement
list = list;
including the side effect of the overwriting the pointer l1
.
The operator can be defined the following way
ShoppingList& ShoppingList::operator+=( const Groceries& c) {
if (size == capacity) {
Groceries* l1 = new Groceries[capacity * 2];
std::copy( list, list + size, l1 );
delete [] list;
list = l1;
capacity *= 2;
}
list[size++]=c;//here is the exception
return *this;
}
Pay attention to that you are using the same identifiers product
and quantity
to declare different entities
class Groceries {
std::string product;
int quantity;
public:
//...
std::string product();
int quantity();
//...
Here is a demonstrative program based on your code.
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
class Groceries {
std::string product;
int quantity;
public:
Groceries() : product("empty"), quantity(0) {};
Groceries(std::string s, int x) : product(s), quantity(x) {};
Groceries(const Groceries& c);
~Groceries() {};
// std::string product();
// int quantity();
void Print();
friend std::ostream & operator <<( std::ostream &os, const Groceries &g )
{
return os << g.product << ": " << g.quantity;
}
};
class ShoppingList{
Groceries* list;
int size = 0, capacity = 2;
public:
//methods
ShoppingList& operator+=( const Groceries& c);
ShoppingList() : list( new Groceries[2]() ) {}
~ShoppingList() { delete [] list; }
friend std::ostream & operator <<( std::ostream &os, const ShoppingList &sl )
{
std::copy( sl.list, sl.list + sl.size,
std::ostream_iterator<Groceries>( os, " " ) );
return os;
}
};
ShoppingList& ShoppingList::operator+=( const Groceries& c) {
if (size == capacity) {
Groceries* l1 = new Groceries[capacity * 2];
std::copy( list, list + size, l1 );
delete [] list;
list = l1;
capacity *= 2;
}
list[size++]=c;//here is the exception
return *this;
}
int main()
{
ShoppingList L;
(L += Groceries("bread", 5)) += Groceries("cheese", 2);
std::cout << L << '\n';
return 0;
}
The program output is
bread: 5 cheese: 2