Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

In this assignment we will create an abstract Container class and a Vector class

ID: 3915078 • Letter: I

Question

In this assignment we will create an abstract Container class and a Vector class, which will be derived from the Container class. The container class will be a blueprint for other derived classes that wish to use a similar public interface. The idea behind our Container class is that we want to write a class that has the ability to dynamically allocate/deallocate an array behind the scenes.

Task 1

Create an ?abstract? template class template? <?typename? T> class? Container {

?// Stuff goes here... };

This class will contain the following ?protected? member variables: ? T*elem

? Will be used as a pointer to an array of elements of type T ? intcap

? Will denote the size of our array

The class will also contain the following ?public? methods

? T&operator[](inti)

? The array access operator, which will be used to retrieve/set an element in our container

? We want this function to be a ?pure virtual function? (i.e. this function will not be implemented in our base Container class)

? Question: Why do we have to return a reference here?

? intsize()

? This function will be used to return the number of elements in our container

? This function should also be a ?pure virtual function

? A destructor

? This function will delete our dynamically allocated ?elem

? This function will be implemented in our Container class

Put all code for task 1 in a file called “Container.hpp”

Task 2

Create a template class ?Vector? that ?publicly inherits ?from our Container class. ?For each method in the class, you must write a short snippet of code that demonstrates its functionality (in your main).? ?The ideal way to do this assignment is to write a function, then test. Don’t just write everything, cross your fingers and hope it works. Trust me; that’s a recipe for disaster.

template? <?typename? T>
class? Vector : ?public? Container<T> {

?// we have to do this because we are templating
// otherwise we would be able to access the protected // members of Container without these using directives ?using? Container<T>::elem;
?using? Container<T>::cap;

};

In addition to our ?elem?, and ?cap? member variables, our Vector class will have the following private member variable:

? intsz

? This will denote the number of elements in our vector (ie. its size)

? Not to be confused with ?cap? which is the size of the underlying dynamically

allocated array.

We will define the following constructors:

? Default constructor
? Initialize ?elem? as a ?nullptr? and ?cap,? ?sz? as 0

? Two fill constructors
? Vector(intn)?-constructaVectorofnelements(sz=n).Dynamicallyallocate

elem to be of size ?cap = 2*n.? Leave the elements uninitialized.
? Vector(intn,Tfill_val)?-?constructaVectorofnelementsjustasbefore,

but initialize each element to be equal to fill_val.

? A copy constructor

? Vector(constVector&V)?--constructaVectortobeacopyofV.Wemust dynamically allocate ?elem? to be the same size as V’s ?elem?, then copy each element of V’s ?elem? to our newly constructed ?elem?. Set ?sz? and ?cap? accordingly.

We must also overload the = operator.
? T&operator=(constVector&V)?-?Workssimilarlytoourcopyconstructor,butwecan

use this to set a vector equal to a copy of another vector using the = operator instead of

CSCI 1300 Summer 2018 Assignment 7

having to construct a new one from scratch with the copy constructor. The main difference between? operator=? and our copy constructor is that ?operator=? will return a reference to itself (i.e. ?return *this?)

Define the following public methods which we will use to access Vector elements:

? T&operator[](inti)?-Thearrayaccessoperator.

? This was a virtual function in our Container class. We will implement it here in our

derived Vector class.

? This function will allow us to both retrieve and/or assign a value to the ith element

of the Vector
? T&front()?-ReturnsareferencetothefirstelementoftheVector ? T&back()?-ReturnsareferencetothelastelementoftheVector

Define the following public methods to get the size of our Vector/elem array

? intsize()? ?- returnsthenumberofelementsinourVector
? intcapacity()??-returnsthesizeofourunderlying?elem?array

Define the following two iterator methods

? T*begin()?-?returnsapointertothebeginningofthevector

? T*end()?-?returnsapointertotheendofthevector

? These methods will enable us to use Vector with the range-for loop

Define the following methods used to add/remove Vector elements

? voidpush_back(constT&val)?-?adds?val?totheendofourvector(growsourVector

by one element)

? We must check to see if there is room in our ?elem? array to add a new element.

? If there isn’t enough room, then we must dynamically allocate a new array with

twice the number of elements as the old one.

? We must then copy all elements in our old array into our new one.

? Finally, we must delete the old array and set ?elem? equal to our new one

? Then we can add ?val? to the next open spot in the array.

? voidpop_back()?-RemoveanelementfromourVector(shrinksbyone)

? We can just reduce ?sz? by one and destroy the element at the end

? To destroy the ith element of ?elem? we can do the following

elem[i].~T() ?//calls elem[i]’s destructor (for types like int, does nothing)

? voidinsert(T*position,constT&val)?-?Inserts?val?into?position?inourVector

? Example: to insert ?val? into the 5th postition of a Vector X we would write

? X.insert(X.begin()+5,val)

? Just like with push_back, we must check if the array is has room for one more

element. If it doesn’t then we do as what we did for push_back to create a new larger array.

Before we can insert an element, we must move all elements to the right of our position right by one. ?Hint: We’ve done this before. Check the array lecture slides.

? Another hint:? ?position? is a pointer to the location we wish to insert into?. I can treat ?position? as an array. (i.e. I can use the ?[]? operator to access elements)

? T*erase(T*position)?-RemovesasingleelementfromourVectorspecifiedby position

? We’ve done this before as well - check the array lecture slides

? Just like in pop_back we must destroy the element

? Returns a pointer to the new location of the element that followed the element we

just erased.

? Doesn’t affect the ?elem? array size, just reduces the Vector size by one.

? void clear()? - Removes all elements from the Vector

? Destroys each element

? Sets the size to zero

? Doen’t affect the size of the ?elem? array

Explanation / Answer

here is your code files:: ------------>>>>>>>>

Container.hpp : --------->>>>>>>

#ifndef CONTAINER_H
#define CONTAINER_H
#include<iostream>

using namespace std;

template<class T>
class Container{
protected:
  T *elem;
  int cap;
public:
  ~Container(){
   delete[] elem;
  }
  virtual T& operator[](int i) = 0;
  virtual int size()const = 0;
};

#endif

Vector.hpp : ---------->>>>>>>>>

#ifndef VECTOR__H__
#define VECTOR__H__
#include "Container.h"

template<class T>
class Vector:public Container<T>{
private:
  int sz;
  void resize(){
   cap = cap*2;
   T *arr = new T[cap];
   for(int i = 0;i<sz;i++){
    arr[i] = elem[i];
   }
   delete[] elem;
   elem = arr;
  }
public:
  using Container<T>::elem;
  using Container<T>::cap;
  Vector(){
   elem = nullptr;
   cap = 0;
   sz = 0;
  }
  Vector(int n){
   elem = new T[2*n];
   cap = 2*n;
   sz = 0;
  }
  Vector(int n,T fill_val):Vector(n){
   for(int i = 0;i<sz;i++){
    elem[i] = fill_val;
   }
  }
  Vector(const Vector &V){
   *this = V;
  }
  T& operator=(const Vector &V){
   if(this == &V){
    return *this;
   }
   delete[] elem;
   cap = V.cap;
   sz = V.sz;
   elem = new T[cap];
   for(int i = 0;i<sz;i++){
    elem[i] = V.elem[i];
   }
   return *this;
  }
  T& operator[](int i){
   if(i >= 0 && i < sz){
    return elem[i];
   }
  }
  T& front(){
   return *this[0];
  }
  int size()const{
   return sz;
  }
  int capacity(){
   return cap;
  }
  T* begin(){
   return &front();
  }
  T* end(){
   return &elem[sz-1];
  }
  void push_back(const T &val){
   if(sz >= cap){
    resize();
   }
   elem[sz++] = val;
  }
  void pop_back(){
   sz--;
   elem[sz].~T();
  }
  void insert(T *position,const T &val){
   if(sz >= cap){
    resize();
   }
   for(T *i = &elem[sz];i > position;i--){
    *i = *(i-1);
   }
   *position = val;
   sz++;
  }
  T* erase(T *position){
   T *cur = position-1;
   for(T *p = position;p < &elem[sz-1];p++){
    *p = *(p+1);
   }
   elem[sz-1].~T();
   sz--;
   return cur;
  }
  void clear(){
   for(int i = 0;i<sz;i++){
    elem[i].~T();
   }
   sz = 0;
  }
};

#endif