0

I am writing code for a game that features a character class with three elements that are other classes. One of these is a Backpack to hold items. The Backpack is created using another class called DynamicArray, which is basically a dynamic array that can hold other objects. I turned the dynamic array class into a class template so that the array can hold any object, and now the Backpack class is not being recognized in my Character class.

Dynamic Array Class Template:

#pragma once
#include <string>
#include <iostream>
using std::ostream;
using std::endl;
#include "potions.h"
#include "character.h"

template<typename TYPE>
class DynamicArray
{
public:
    // Constructors
    DynamicArray();
    ~DynamicArray();
    DynamicArray(const DynamicArray & copy);

    // Op Equals
    DynamicArray & operator =(const DynamicArray & rhs);

    // Getters
    int getElements();
    TYPE getElement(int index);

    // Manipulate and view contents
    void Insert(const TYPE & add);
    void Delete(const TYPE & rmv);
    void display();

    // Overloaded operators
    TYPE & operator [](int index);
    friend ostream & operator << (ostream & out, const DynamicArray & d);

private:
    // Member variables
    TYPE * m_array;
    int m_elements;

    // Find function
    int Find(const TYPE & target);
};

/**********************************************************************
* Purpose: Default constructor
*
* Postcondition:
* Initializes m_array and m_elements to nullptr and 0
************************************************************************/
template<typename TYPE>
DynamicArray<TYPE>::DynamicArray() : m_array(nullptr), m_elements(0)
{

}

/**********************************************************************
* Purpose: Destructor
*
* Postcondition:
* Delete m_array
************************************************************************/
template<typename TYPE>
DynamicArray<TYPE>::~DynamicArray()
{
    if (m_array != nullptr)
    {
        delete[] m_array;
    }
}

/**********************************************************************
* Purpose: Copy construcxtor
*
* Postcondition:
* Take an object as an argument and copy the contents to a new object
************************************************************************/
template<typename TYPE>
DynamicArray<TYPE>::DynamicArray(const DynamicArray & copy) : m_elements(copy.m_elements)
{
    int arrSize = copy.m_elements;
    m_array = new TYPE[arrSize];

    for (int i = 0; i < arrSize; i++)
    {
        m_array[i] = copy.m_array[i];
    }
}

/**********************************************************************
* Purpose: Op equals
*
* Postcondition:
* Perform a deep copy of one object to another using the = operator
************************************************************************/
template<typename TYPE>
DynamicArray<TYPE> & DynamicArray<TYPE>::operator =(const DynamicArray & rhs)
{
    if (this != &rhs)
    {
        delete[] m_array;

        m_elements = rhs.m_elements;
        m_array = new TYPE[m_elements];

        for (int i = 0; i < m_elements; i++)
        {
            m_array[i] = rhs.m_array[i];
        }
    }

    return *this;
}

/**********************************************************************
* Purpose: Elements getter
*
* Postcondition:
* Return the number of elements
************************************************************************/
template<typename TYPE>
int DynamicArray<TYPE>::getElements()
{
    return m_elements;
}

template<typename TYPE>
TYPE DynamicArray<TYPE>::getElement(int index)
{
    return m_array[index];
}

/**********************************************************************
* Purpose: Insert item into dynamic array
*
* Postcondition:
* Increment m_elements by 1
* Add a new potion to the dynamic array
************************************************************************/
template<typename TYPE>
void DynamicArray<TYPE>::Insert(const TYPE & add)
{
    if (m_elements != 0)
    {
        TYPE * temp = new TYPE[m_elements];

        for (int i = 0; i < m_elements; i++)
        {
            temp[i] = m_array[i];
        }

        delete[] m_array;

        m_array = new TYPE[m_elements + 1];

        for (int i = 0; i <= m_elements; i++)
        {
            if (i == m_elements)
            {
                m_array[i] = add;
            }
            else
            {
                m_array[i] = temp[i];
            }
        }

        delete[] temp;

        m_elements++;
    }
    else
    {
        m_elements++;

        m_array = new TYPE[m_elements]{ add };
    }
}

/**********************************************************************
* Purpose: Delete item from dynamic array
*
* Precondition: Array must contain at least one item
*
* Postcondition:
* Decrement the number of elements
* Find an item in the dynamic array
* Remove an item from the dynamic array
************************************************************************/
template<typename TYPE>
void DynamicArray<TYPE>::Delete(const TYPE & rmv)
{
    if (m_elements != 0)
    {
        int index = Find(rmv);

        if (index != -1)
        {
            TYPE * temp = new TYPE[(m_elements - 1)];

            for (int i = 0; i < m_elements; i++)
            {
                if (i < index)
                {
                    temp[i] = m_array[i];
                }
                else if (i > index)
                {
                    temp[(i - 1)] = m_array[i];
                }
            }

            delete[] m_array;

            m_elements--;

            m_array = new TYPE[m_elements];

            for (int i = 0; i < m_elements; i++)
            {
                m_array[i] = temp[i];
            }

            delete[] temp;
        }
    }
}

/**********************************************************************
* Purpose: Display the elements of the array
*
* Postcondition:
* Send the array elements out to the console
************************************************************************/
template<typename TYPE>
void DynamicArray<TYPE>::display()
{
    for (int i = 0; i < m_elements; i++)
    {
        m_array[i].display();
    }
}

/**********************************************************************
* Purpose: Overloaded subscript operator
*
* Postcondition:
* Return the array object given by the index
************************************************************************/
template<typename TYPE>
TYPE & DynamicArray<TYPE>::operator [](int index)
{
    return m_array[index];
}

/**********************************************************************
* Purpose: Overloaded Stream Insertion Operator
*
* Postcondition: Overloads the stream insertion operator in order to
* output the contents of the character using cout
*
************************************************************************/
template<typename TYPE>
ostream & operator << (ostream & out, const DynamicArray<TYPE> & d)
{
    for (int i = 0; i < d.m_elements; i++)
    {
        out << d.m_array[i] << endl;
    }

    return out;
}

/**********************************************************************
* Purpose: Find an item in the dynamic array
*
* Postcondition:
* Return the index of the found item
************************************************************************/
template<typename TYPE>
int DynamicArray<TYPE>::Find(const TYPE & target)
{
    int found = -1;

    for (int i = 0; i < m_elements; i++)
    {
        if (m_array[i] == target)
        {
            found = i;
        }
    }

    return found;
}

Backpack.h File

#pragma once
#include "dynamicarray.h"
#include "coinPouch.h"
#include "string.h"
#include "potions.h"

class Backpack
{
public:
    // Constructors
    Backpack();
    Backpack(DynamicArray<Potion> potions);
    Backpack(const Backpack & copy);
    ~Backpack();

    // Overloaded operators
    Backpack & operator = (const Backpack & rhs);
    friend ostream & operator << (ostream & out, const Backpack & c);

    // Manipulate and view contents
    void addPotion(const Potion & add);
    void usePotion(const Potion & rm);
    void displayContents();

    // Getters
    int getNumber();
    DynamicArray<Potion> getPotions();
    Potion getPotion(int index);

private:
    DynamicArray<Potion> m_potions;
    int m_number;
};

Character.h File

#pragma once
#include <iostream>
using std::ostream;
#include "string.h"
#include "coinPouch.h"
#include "backpack.h"
#include "dynamicarray.h"
#include "potions.h"


class Character
{
public:
    // Constructors
    Character();
    Character(String name);
    Character(String name, CoinPouch wallet, Backpack storage);
    Character(const Character & copy);

    // Destructor
    ~Character();

    // Overloaded operators
    Character & operator =(const Character & rhs);
    friend ostream & operator << (ostream & out, const Character & c);

    // Manipulate and display contents
    void purchase(int p, int g, int s, int c);
    void income(int p, int g, int s, int c);
    void addPotion(const Potion & toAdd);
    void checkBalance();
    void checkBackpack();
    void changeName(const String & newN);
    void display();

    // Getters and setters
    String getName();
    CoinPouch getWallet();
    Backpack getStorage();
    void setName(String name);
    void setWallet(CoinPouch wallet);
    void setStorage(Backpack storage);

    // Random Number Generator
    int randomNum();

private:
    String m_name;
    CoinPouch m_wallet;
    Backpack m_storage;

};

Errors:

Severity    Code    Description Project File    Line    Suppression State
Error   C4430   missing type specifier - int assumed. Note: C++ does not support default-int    cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    49  
Error   C3646   'm_storage': unknown override specifier cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    49  
Error   C2061   syntax error: identifier 'Backpack' cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    41  
Error   C2059   syntax error: '('   cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    38  
Error   C2238   unexpected token(s) preceding ';'   cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    38  
Error   C3646   'getStorage': unknown override specifier    cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    38  
Error   C2061   syntax error: identifier 'Backpack' cst136_lab1_ehayes  c:\users\elijah hayes\documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\character.h    16  

I'm just starting out with class templates and not sure what to expect. Been trying to figure this out for a while, any help is appreciated. Thanks!

EDIT: I believe the issue was circular dependency, and I think that I fixed that by removing the Character.h and Potions.h include in the Dynamic Array Class. That was the only thing I changed. Now I am receiving this error:

Severity Code Description Project File Line Suppression State
Error LNK2019 unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class DynamicArray<class Potion> const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABV?$DynamicArray@VPotion@@@@@Z) referenced in function "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,class Backpack const &)" (??6@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@std@@AAV01@ABVBackpack@@@Z) cst136_lab1_ehayes C:\Users\Elijah Hayes\Documents\cst136_lab1_ehayes-master\cst136_lab1_ehayes\backpack.obj 1 
empoweredev
  • 47
  • 10
  • I believe you have a circular include path. – drescherjm Nov 26 '18 at 23:58
  • 1
    Possible duplicate of [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) – drescherjm Nov 26 '18 at 23:58
  • Unrelated: You may find visual Studio's Output tab more useful than the Error List tab. The Error List often truncates the error message severely, limiting the information that could be available to you. In addition the Output tab is raw text and really easy to cut and paste. – user4581301 Nov 27 '18 at 00:25
  • @drescherjm Thank you for the link, that makes sense. I now believe I understand circular dependency, but how is that affecting my code? Sorry, I was looking through what I had and wasn't sure where the issue was. – empoweredev Nov 27 '18 at 00:40
  • To me I see that Character.h contains a Backpack object, and Backpack is made of a DynamicArray, but then the DynamicArray contains a pointer of a templated type. It doesn't seem like that would cause an issue with circular dependency like what was described in the other question, though I'm sure I'm missing something. – empoweredev Nov 27 '18 at 00:42
  • @empoweredev The problem is that `dynamicarray.h` is including `character.h` and `potion.h`, so these two files will be included possibly before the rest of `dynamicarray.h` is. There is no reason for these two includes, is there? –  Nov 27 '18 at 00:52
  • Why does `dynamicarray.h` include `character.h` ? I think this is your problem. – drescherjm Nov 27 '18 at 01:11
  • I added Character.h and Potion.h because I assumed it was necessary if those elements were going to be used in the templated class. Is that not the case then? I wanted to make a dynamic array of character objects in main. – empoweredev Nov 27 '18 at 01:59
  • No its not necessary. – drescherjm Nov 27 '18 at 02:01
  • Alright, removed those includes from the dynamicarray.h file and now I have this error. Edit: Too long to include here, I will edit it in to the main post. – empoweredev Nov 27 '18 at 02:03
  • 2
    @empoweredev This question is unrelated and should probably be asked in a new question. Anyway this is a mistake in `dynamicarray.h`, the `operator<<` friend should be either inline or should be referring to the templated version defined later, but to do so it would need to be forward-declared before the class definition. (see "Template friend operators" in https://en.cppreference.com/w/cpp/language/friend) –  Nov 27 '18 at 02:42
  • Awesome, that fixed it. Works like a charm now. Thank you so much! Saved me a ton of hassle from my own dumb mistakes. Hope you have a great day. – empoweredev Nov 27 '18 at 03:08

0 Answers0