Mike Bagnasco
Mike Bagnasco

Reputation: 97

Overriding Pure Virtual Functions from a Template Base Class

So i'm trying to make an array-based bag which behaves like a stack in the sense that it adds to the top but it can also inspect and remove elements that are not at the top.

For my assignment, I was given this bagADT class template by my professor with pure virtual functions.

#ifndef BAGADT_H
#define BAGADT_H

#include <stdlib.h>
#include "book.h"

template <typename E>
class Bag {
public:
    Bag() {}            // base constructor
    virtual ~Bag() {}   // base destructor
// Insert a new item into the bag -- return false if fails and true if
// successful
virtual bool addItem(const E& item) = 0;

// Looks for 'item' in the bag and if found updates 'item' with the 
// bag value and returns true.  Otherwise 'item' is left unchanged
// and the method returns false.
virtual bool remove(E& item) = 0;

// Removes the top record from the bag, puts it in returnValue, and
// returns true if the bag is not empty.  If the bag is empty the 
// function returns false and returnValue remains unchanged.
virtual bool removeTop(E& returnValue) = 0;

// Finds the record using returnValue and if the record is found updates
// returnValue based on the contents of the bag and returns true.  If the
// record is not found the function returns false.  Works just like remove()
// except that the found record is not removed from the bag.
virtual bool find(E& returnValue) const = 0;

// Inspect the top of the bag.  If the bag is empty return
// false and leave 'item' unchanged; otherwise, return true and update 
// 'item' with the contents of the bag.
virtual bool inspectTop(E& item) const = 0;

// empties the bag
virtual void emptyBag() = 0;

// use the += operator to add an item to the bag
virtual bool operator+=(const E& addend) = 0;

// get the size of the bag
virtual int size() const = 0;

// get the capacity of the bag
virtual int bagCapacity() const = 0;
};

#endif  /* BAGADT_H */

Given this, I created an inherited ABag class.

#pragma once
#include "bagADT.h"


#ifndef ABAG_H
#define ABAG_H

template <typename E>
class ABag : public Bag<E>
{
public:
    ABag(int size = 10)
    {
        maxSize = size;
        top = 0;
        listArray = new E[size];
    }
     virtual ~ABag()
    {
        delete[] listArray;
    }

    template <typename E>
    bool addItem(const E& item)
    {
        if (top < maxSize)
        {
            listArray[top] = item;
            top++;
            return true;
        }
        else
            return false;

    }


    // Looks for 'item' in the bag and if found updates 'item' with the 
    // bag value and returns true.  Otherwise 'item' is left unchanged
    // and the method returns false.
    //template <typename E>
    bool remove(E& item)
    {
        for (int i = 0; i <= top; i++)
        {
            if (listArray[i] == item)
            {
                for (int j = i + 1; j <= top; j++)
                {
                    listArray[i] = listArray[j];
                    i++;
                }
                top--;
                return true;
            }
        }
        return false;
    }


    // Removes the top record from the bag, puts it in returnValue, and
    // returns true if the bag is not empty.  If the bag is empty the 
    // function returns false and returnValue remains unchanged.
    //template <typename E>
    bool removeTop(E& returnValue)
    {
        if (top > 0)
        {
            returnValue = listArray[top--];
        }


    }


    // Finds the record using returnValue and if the record is found updates
    // returnValue based on the contents of the bag and returns true.  If the
    // record is not found the function returns false.  Works just like remove()
    // except that the found record is not removed from the bag.
    //template <typename E>
    bool find(E& returnValue)
    {

    }

    // Inspect the top of the bag.  If the bag is empty return
    // false and leave 'item' unchanged; otherwise, return true and update 
    // 'item' with the contents of the bag.
    //template <typename E>
    bool inspectTop(E& item)
    {
        if (top != 0)
        {
            item = listArray[top];
            return true;
        }
        else
            return false;
    }

    // empties the bag
    //template <typename E>
    void emptyBag()
    {
        top = 0;
    }

    // use the += operator to add an item to the bag
    //template <typename E>
    bool operator+=(const E& addEnd)
    {

    }

    // get the size of the bag
    //template <typename E>
    int size()
    {
        return top;
    }

    // get the capacity of the bag
    //template <typename E>
    int bagCapacity()
    {
        return maxSize;
    }

private:
    int maxSize;
    int top;
    E *listArray;
};


/*template <typename E>
ABag<E>::ABag()
{
    int size = 10
    maxSize = size;
    top = 0;
    listArray = new E[size];
}


template <typename E>
ABag<E>::~ABag()
{
    delete [] listArray;
}*/
#endif

Here is my source.cpp trying to instantiate an object from the class.

#include <iostream>
#include <string>
#include "ABag.h"
#include "BDictionary.h"

using namespace std;

int main(){
    ABag<int> myBag;

    cout << myBag.bagCapacity();

    system("Pause");
    return 0;
}

And for some reason. I keep getting this error.

error C2259: 'ABag<int>' : cannot instantiate abstract class

I have trekked all across stack exchange and text books and forum after forum trying to figure why this won't work. I understand what the error is. I get that you can't make an object from an abstract class. But I have tried a dozen different ways to try to override the pure virtual functions from the base class and I can't. There's an IntelliSense error telling me that each of the pure virtual functions have no overrider.

Can anyone please help me out?

Upvotes: 1

Views: 2041

Answers (1)

3442
3442

Reputation: 8576

This is the problem:

template <typename E>
bool addItem(const E& item)
{
    if (top < maxSize)
    {
        listArray[top] = item;
        top++;
        return true;
    }
    else
        return false;

}

You see, any subclass D of an abstract class C is considered abstract itself, unless D implements absolutely all pure virtual methods of C. Bag<E>'s addItem() is a pure virtual function with signature bool Bag<E>::addItem( const E& ). On the other hand, ABag<E>'s addItem() is a function template that takes a type template parameter named E, which shadows the other E in ABag<E>. Once instantiated, it will result in a function of signature bool ABag<E1>::addItem<E2>( const E2& ).

The important bit here is that a function template is not the same thing as a function. You can instantiate a function template into a function, but both concepts by themselves are incompatible. The function template in ABag<E> is not implementing the respective pure virtual function in Bag<E>, since their signatures are inherently incompatible. This also happens when you don't match constness. A function with signature void foo( int ) is not compatible with void foo( int ) const. The former simply won't override/implement the later under no circumstances.

Upvotes: 2

Related Questions