Home > Back-end >  How do I adjust my code to access the original member and not a copy of it?
How do I adjust my code to access the original member and not a copy of it?

Time:04-10

I have a class called Child that holds a name and a list of string items. Different child objects are stored in a separate list, sort of as a nested list. The representation is:

List<"Child"> [Child1(name, List<"string">), Child2(name, List<"string">), etc.]

My objective is to create two functions: insertChild() and insertPresent(). The first one works, where the idea is to insert a child object into List(Child) with a specified name and List<"string">. Where I'm having trouble is with insertPresent(), where it is supposed to search List<"Child"> given a name and, once there's a match, add a present (string) to that Child object's List<"string">.

The problem appears to be I'm accessing a local copy of the List<"string"> when calling getList(), which explains why there appears to be no errors and the original list remains untouched after calling insertPresent(). How do I implement the changes to access the original list and not the copy? Here's the code:

ArrayList.h:

template<class ItemType>
class ArrayList
{
private:
    static const int DEFAULT_CAPACITY = 5; // Small capacity to test for a full list 
    ItemType items[DEFAULT_CAPACITY];      // Array of list items
protected:
    int itemCount;                         // Current count of list items 
    int maxItems;                          // Maximum capacity of the list
    
public:
   ArrayList();
   // Copy constructor and destructor are supplied by compiler
   
   bool isEmpty() const;
   int getLength() const;
   bool insert(int newPosition, const ItemType& newEntry);
   bool remove(int position);
   void clear();
   
   /** @throw PrecondViolatedExcep if position < 1 or 
                                      position > getLength(). */
   ItemType getEntry(int position) const throw(PrecondViolatedExcep);

   /** @throw PrecondViolatedExcep if position < 1 or 
                                      position > getLength(). */
   void setEntry(int position, const ItemType& newEntry) throw(PrecondViolatedExcep);
}; // end ArrayList

template<class ItemType>
ArrayList<ItemType>::ArrayList() : itemCount(0), maxItems(DEFAULT_CAPACITY)
{
}  // end default constructor

template<class ItemType>
bool ArrayList<ItemType>::isEmpty() const
{
    return itemCount == 0;
}  // end isEmpty

template<class ItemType>
int ArrayList<ItemType>::getLength() const
{
    return itemCount;
}  // end getLength

template<class ItemType>
bool ArrayList<ItemType>::insert(int newPosition, const ItemType& newEntry)
{
    bool ableToInsert = (newPosition >= 1) && (newPosition <= itemCount   1) &&
        (itemCount < maxItems);
    if (ableToInsert)
    {
        // Make room for new entry by shifting all entries at
        // positions >= newPosition toward the end of the array
        // (no shift if newPosition == itemCount   1)
        for (int pos = itemCount; pos >= newPosition; pos--)
            items[pos] = items[pos - 1];

        // Insert new entry
        items[newPosition - 1] = newEntry;
        itemCount  ;  // Increase count of entries
    }  // end if

    return ableToInsert;
}  // end insert

template<class ItemType>
bool ArrayList<ItemType>::remove(int position)
{
    bool ableToRemove = (position >= 1) && (position <= itemCount);
    if (ableToRemove)
    {
        // Remove entry by shifting all entries after the one at
        // position toward the beginning of the array
        // (no shift if position == itemCount)
        for (int fromIndex = position, toIndex = fromIndex - 1; fromIndex < itemCount;
            fromIndex  , toIndex  )
            items[toIndex] = items[fromIndex];

        itemCount--;  // Decrease count of entries
    }  // end if

    return ableToRemove;
}  // end remove

template<class ItemType>
void ArrayList<ItemType>::clear()
{
    itemCount = 0;
}  // end clear

template<class ItemType>
ItemType ArrayList<ItemType>::getEntry(int position) const throw(PrecondViolatedExcep)
{
    // Enforce precondition
    bool ableToGet = (position >= 1) && (position <= itemCount);
    if (ableToGet)
        return items[position - 1];
    else
    {
        string message = "getEntry() called with an empty list or ";
        message = message   "invalid position.";
        throw(PrecondViolatedExcep(message));
    }  // end if
}  // end getEntry

template<class ItemType>
void ArrayList<ItemType>::setEntry(int position, const ItemType& newEntry) throw(PrecondViolatedExcep)
{
    // Enforce precondition
    bool ableToSet = (position >= 1) && (position <= itemCount);
    if (ableToSet)
        items[position - 1] = newEntry;
    else
    {
        string message = "setEntry() called with an empty list or ";
        message = message   "invalid position.";
        throw(PrecondViolatedExcep(message));
    }  // end if
}  // end setEntry

Child.h:

#include "ArrayList.h"

class Child
{
private:
    string name;
    ArrayList<string> presents;

public:
    string getName() const;
    ArrayList<string> getList() const;
    void setName(string name);
    void setList(ArrayList<string> aList);
};

string Child::getName() const {
    return name;
}

ArrayList<string> Child::getList() const {
    return presents;
}

void Child::setName(string name) {
    this->name = name;
}

void Child::setList(ArrayList<string> aList) {
    this->presents = aList;
}

NiceArrayList.h: List<"Child">

#include <string>
#include "Child.h"
using namespace std;

template<class ItemType>
class NiceArrayList : public ArrayList<ItemType>
{
public:
    /** Inserts an object containing name and aList into this list at a given position.
    @pre  None.
    @post  If 1 <= position <= getLength()   1 and the insertion is
       successful, name and aList is at the given position in the nice list,
       other entries are renumbered accordingly, and the returned
       value is true.
    @param position  The list position at which to insert the object.
    @param name  The string assigned to the object inserted into this list.
    @param aList  The list assigned to the object inserted into this list.
    @return  True if insertion is successful, or false if not. */
    bool insertChild(int position, string name, const ArrayList<string>& aList);

    /** Inserts a new entry to the gift list inside an object from this
        list given a name.
    @pre  The parameter name must be in an object in this list.
    @post  If 1 <= position <= getLength()   1 and the insertion is
       successful, newEntry is at the given position in the gift list,
       other entries are renumbered accordingly, and the returned
       value is true.
    @param position  Theobject list position at which to insert the new entry.
    @param name  The string used to identify the object in this list.
    @param newEntry  The entry to insert into the object's list.
    @return  True if removal is successful, or false if not. */
    bool insertPresent(string name, string newEntry);
};

template<class ItemType>
bool NiceArrayList<ItemType>::insertChild(int position, string name, const ArrayList<string>& aList) {
    bool ableToInsert = false;
    Child aChild;
    aChild.setName(name);
    aChild.setList(aList);
    ableToInsert = this->insert(position, aChild);
    return ableToInsert;
}

template<class ItemType>
bool NiceArrayList<ItemType>::insertPresent(string name, string newEntry) {
    bool ableToInsert = false;
    int length = this->getLength();
    int position = 0;
    for (int i = 1; i <= length; i  ) {
        position  ;
        if (this->getEntry(i).getName() == name) {
            break;
        }
    }
    //THE PROBLEM APPEARS TO BE HERE! THE INSERT DOES NOT UPDATE THE LIST!
    ableToInsert = this->getEntry(position).getList().insert(1, newEntry);
    return ableToInsert;
}

Sample main to test:

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

int main() {

    ArrayList<string> aList1;
    aList1.insert(1, "PS4");
    aList1.insert(2, "PS5");
    aList1.insert(3, "Toy Car");

    NiceArrayList<Child> nice;
    nice.insertChild(1, "John", aList1);
    nice.insertPresent("John", "Phone");

    return 0;
}

CodePudding user response:

Your problem is here

ArrayList<string> Child::getList()  const {
    return presents;
}

This is returning a copy of presents, So thios line only updates the copy

ableToInsert = this->getEntry(position).getList().insert(1, newEntry);

You need

ArrayList<string> & Child::getList()   {
    return presents;
}

Note the removal of the const too

and here

ArrayList<string> &getList() ;

same for getEntry on ArrayList, same fix

CodePudding user response:

getList() was returning a copy of the sublist, so I turned the presents attribute into a pointer of the list array and made getList() return a reference to the array. Updated Child class:

Child.h:

#include "ArrayList.h"

class Child
{
private:
    string name;
    ArrayList<string>* presents;

public:
    
    string getName() const;
    ArrayList<string>& getList() const;
    void setName(string name);
    void setList(ArrayList<string>& aList);
};

string Child::getName() const {
    return name;
}

ArrayList<string>& Child::getList() const{
    return *presents;
}

void Child::setName(string name) {
    this->name = name;
}

void Child::setList(ArrayList<string>& aList) {
    this->presents = &aList;
}
  • Related