I was given 4 files, ArrayBag.cpp/.hpp and Animal.cpp/.hpp. The goal is to create a new class, ZooRecord and implement it in respective cpp and hpp files. This class inherits from ArrayBag and stores Animal objects.
// Header file for an array-based implementation of the ADT bag.
#ifndef ARRAY_BAG_
#define ARRAY_BAG_
#include <vector>
#include <string>
template<class T>
class ArrayBag
{
public:
/** default constructor**/
ArrayBag();
/**
@return item_count_ : the current size of the bag
**/
int getCurrentSize() const;
/**
@return true if item_count_ == 0, false otherwise
**/
bool isEmpty() const;
/**
@return true if new_etry was successfully added to items_, false otherwise
**/
bool add(const T& new_entry);
/**
@return true if an_etry was successfully removed from items_, false otherwise
**/
bool remove(const T& an_entry);
/**
@post item_count_ == 0
**/
void clear();
/**
@return true if an_etry is found in items_, false otherwise
**/
bool contains(const T& an_entry) const;
/**
@return the number of times an_entry is found in items_
**/
int getFrequencyOf(const T& an_entry) const;
/**
@return a vector having the same cotntents as items_
**/
std::vector<T> toVector() const;
/** display the contents of the bag to standard output in the form “item1, item2, … , itemN\n” **/
std::string display();
void operator+=(const ArrayBag<T>& a_bag);
void operator-=(const ArrayBag<T>& a_bag);
void operator/=(const ArrayBag<T>& a_bag);
protected:
static const int DEFAULT_CAPACITY = 200; //max size of items_
T items_[DEFAULT_CAPACITY]; // Array of bag items
int item_count_; // Current count of bag items
/**
@param target to be found in items_
@return either the index target in the array items_ or -1,
if the array does not containthe target.
**/
int getIndexOf(const T& target) const;
}; // end ArrayBag
#endif
/** Implementation file for the class ArrayBag.
@file ArrayBag.cpp */
#include "ArrayBag.hpp"
#include <iostream>
/** default constructor**/
template<class T>
ArrayBag<T>::ArrayBag(): item_count_(0)
{
} // end default constructor
/**
@return item_count_ : the current size of the bag
**/
template<class T>
int ArrayBag<T>::getCurrentSize() const
{
return item_count_;
} // end getCurrentSize
/**
@return true if item_count_ == 0, false otherwise
**/
template<class T>
bool ArrayBag<T>::isEmpty() const
{
return item_count_ == 0;
} // end isEmpty
/**
@return true if new_etry was successfully added to items_, false otherwise
**/
template<class T>
bool ArrayBag<T>::add(const T& new_entry)
{
bool has_room = (item_count_ < DEFAULT_CAPACITY);
if (has_room)
{
for(int i = 0; i < item_count_; i++) {
if (items_[i] == new_entry) {
return false; // duplicate item found
}
}
items_[item_count_] = new_entry;
item_count_++;
return true;
} // end if
return false;
} // end add
/**
@return true if an_etry was successfully removed from items_, false otherwise
**/
template<class T>
bool ArrayBag<T>::remove(const T& an_entry)
{
int found_index = getIndexOf(an_entry);
bool can_remove = !isEmpty() && (found_index > -1);
if (can_remove)
{
item_count_--;
items_[found_index] = items_[item_count_];
} // end if
return can_remove;
} // end remove
/**
@post item_count_ == 0
**/
template<class T>
void ArrayBag<T>::clear()
{
item_count_ = 0;
} // end clear
/**
@return the number of times an_entry is found in items_
**/
template<class T>
int ArrayBag<T>::getFrequencyOf(const T& an_entry) const
{
int frequency = 0;
int cun_index = 0; // Current array index
while (cun_index < item_count_)
{
if (items_[cun_index] == an_entry)
{
frequency++;
} // end if
cun_index++; // Increment to next entry
} // end while
return frequency;
} // end getFrequencyOf
/**
@return true if an_etry is found in items_, false otherwise
**/
template<class T>
bool ArrayBag<T>::contains(const T& an_entry) const
{
return getIndexOf(an_entry) > -1;
} // end contains
/**
@return a vector having the same cotntents as items_
**/
template<class T>
std::vector<T> ArrayBag<T>::toVector() const
{
std::vector<T> bag_contents;
for (int i = 0; i < item_count_; i++)
bag_contents.push_back(items_[i]);
return bag_contents;
} // end toVector
template<class T>
std::string ArrayBag<T>::display() {
std::string result;
for (int i = 0; i < item_count_; i++) {
result += std::to_string(items_[i]);
if(i < item_count_ -1 )
result += ", ";
}
result += '\n';
return result;
}
template<class T>
void ArrayBag<T>::operator+=(const ArrayBag<T>& a_bag)
{
for (int i = 0; i < a_bag.item_count_; i++)
{
add(a_bag.items_[i]);
}
}
template<class T>
void ArrayBag<T>::operator-=(const ArrayBag<T>& a_bag)
{
for (int i = 0; i < a_bag.item_count_; i++)
{
remove(a_bag.items_[i]);
}
}
template<class T>
void ArrayBag<T>::operator/=(const ArrayBag<T>& a_bag)
{
int i = 0;
while (i < item_count_)
{
if (!a_bag.contains(items_[i]))
{
remove(items_[i]);
}
else
{
i++;
}
}
}
// ********* PRIVATE METHODS **************//
/**
@param target to be found in items_
@return either the index target in the array items_ or -1,
if the array does not containthe target.
**/
template<class T>
int ArrayBag<T>::getIndexOf(const T& target) const
{
bool found = false;
int result = -1;
int search_index = 0;
// If the bag is empty, item_count_ is zero, so loop is skipped
while (!found && (search_index < item_count_))
{
if (items_[search_index] == target)
{
found = true;
result = search_index;
}
else
{
search_index++;
} // end if
} // end while
return result;
} // end getIndexOf```
#ifndef ZOO_RECORD_HPP
#define ZOO_RECORD_HPP
#include "ArrayBag.hpp"
#include "Animal.hpp"
#include <fstream>
#include <sstream>
class ZooRecord : public ArrayBag<Animal>
{
public:
//default constructor for empty record
ZooRecord();
/**parameterized constructor
@pre the input file is expected to be in CSV
(comma separated value) format as:
"animal_name,hair,feathers,eggs,milk,airborne,aquatic,predator,toothed,
backbone,breathes,venomous,fins,legs,tail,domestic,catsize,class_type\n"
@param input_file_name the name of the input file
@post adds Animal objects to record as per the data in the input file
**/
ZooRecord(std::string input_file_name);
/**@post displays all animals in record, one per line by calling animal's
display method” **/
void display();
};
#endif
#include "ZooRecord.hpp"
//default constructor for empty record
ZooRecord::ZooRecord()
{
//default constructor for ArrayBag is called automatically
}
/**parameterized constructor
@pre the input file is expected to be in CSV
(comma separated value) format as:
"animal_name,hair,feathers,eggs,milk,airborne,aquatic,predator,toothed,
backbone,breathes,venomous,fins,legs,tail,domestic,catsize,class_type\n"
@param input_file_name the name of the input file
@post adds Animal objects to record as per the data in the input file
**/
ZooRecord::ZooRecord(std::string input_file_name)
{
std::ifstream input_file(input_file_name);
std::string line;
while(std::getline(input_file,line))
{
std::stringstream line_stream(line);
std::string cell;
std::getline(line_stream, cell, ',');
std::string name = cell;
//parse remaining cells and set values for domestic and predator
bool domestic, predator;
std::getline(line_stream, cell, ',');
domestic = cell == "1";
std::getline(line_stream, cell, ',');
predator = cell == "1";
//create a new animal object with the parsed data
Animal new_animal(name,domestic,predator);
// add the new animal to the record
add(new_animal);
}
}
/**@post displays all animals in record, one per line by calling animal's
display method” **/
void ZooRecord::display()
{
for(int i = 0; i < item_count_; i++)
{
items_[i].display();
}
}
However, when compiling I get this error:
ZooRecord.cpp:4: undefined reference to ArrayBag<Animal>::ArrayBag()' c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: C:\Users\super\AppData\Local\Temp\ccaUMYah.o: in function
ZooRecord::ZooRecord(std::__cxx11::basic_string<char, std::char_traits, std::allocator >)':
ZooRecord.cpp:17: undefined reference to ArrayBag<Animal>::ArrayBag()' c:/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/12.2.0/../../../../x86_64-w64-mingw32/bin/ld.exe: ZooRecord.cpp:36: undefined reference to
ArrayBag::add(Animal const&)'
collect2.exe: error: ld returned 1 exit status
I expected the program to compile correctly but I kept getting the undefined reference issue even though I thought it was defined.
I compiled this on vsc using g++.exe build active file. I dont understand why it's giving me undefined reference, does it have something to do with changing T to Animal in the derived class? Please help.