Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a virtual destructor in C++

I'm starting to learn c++ but I'm stuck in the destructor. We need to implement a vector and this is what I have so far.

#include<string.h>
#include<cassert>
#include<iostream>

using namespace std;
template<class T>
class Vector {
    template<class U> friend ostream& operator<<(ostream&, const Vector<U>&);
private:
    T* data;
    unsigned len;
    unsigned capacity;
public:
    Vector(unsigned = 10);
    Vector(const Vector<T>&);
    virtual ~Vector(void);
    Vector<T>& operator =(const Vector<T>&);
    bool operator==(const Vector<T>&);
    T& operator[](unsigned);
};

//PROBLEM! 
template <class T>
~ Vector() {
    delete data;

}

template<class T>
Vector<T>::Vector(unsigned int _capacity)
{
    capacity = _capacity;
    len = _capacity;
    data = new T[_capacity];
}

template<class T>
Vector<T>::Vector(const Vector<T> & v)
{
    len = v.len;
    capacity = v.capacity;
    data = new T[len];
    for (unsigned int i = 0; i < len; i++)
        data[i] = v.data[i];
}



template<class T>
Vector<T> & Vector<T>::operator = (const Vector<T> & v)
{
    delete[ ] data;
    len = v.len;
    capacity = v.capacity;
    data = new T [len];
    for (unsigned int i = 0; i < len; i++)
        data[i] = v.data[i];
    return *this;
}

template<class T>
bool Vector<T>::operator == (const Vector<T> & v)
{
    bool check = true;
    check &= (len == v.len);
    if (!check) return false;
    check &= (capacity == v.capacity);
    if (!check) return false;
    for (unsigned int i = 0; i < len; i++) {
        check &= (data[i] == v.data[i]);
        if (!check) return false;

    }
    return true;
}

template<class T>
T& Vector<T>::operator[](unsigned int index)
{
    return data[index];
}

The interface is given and I need to implement it. But this is so different from C and Java, that I'm a bit lost.


In the second exercise we need to implement something like this using a) the previous Vector implementation as derived class and b) the Vector as composition class, so maybe we will use the virtual destructor in one of the approaches?

void testAssociativeArray() { 
AssociativeArray<String, int> table;
 table["abc"] = 15;
 table["jkl"] = 12;
 table["xyz"] = 85;
 assert(table["jkl"], 12);
 }

template<class P, class Q>
class Pair {
P p;
Q q; public:
      Pair(const P& _p = P(), const Q& _q = Q()): p(_p), q(_q) {}
      P& objectP() {return p;}
      Q& objectQ() {return q;}
};
like image 578
Daniel Avatar asked Oct 26 '12 12:10

Daniel


3 Answers

First off, why do you think that the destructor should be virtual? Are you using polymorphism?

Second, you are using delete incorrectly for your array.

Since you used:

data = new T[length];

You must use the array syntax:

delete [] data;

Third, you need to put the namespace in front of all of your class function definitions:

template <class T>
Vector<T>::~Vector()
{
    delete [] data;
}

And just for your information, you declare the destructor like so...

virtual ~Vector(void);

As I mentioned, virtual is unnecessary unless you are using this class as a base or derived class in a polymorphic manner. For more information on when you need to use virtual destructors, look at the answer to this question.

In addition, the void in the parameters is also unnecessary. This used to be required in old C standard, but it is not in C++.

You should be able to declare it like so:

~Vector();

If you define AssociativeArray<P,Q> with a has-a relationship to Vector<T>, then you can simply make the class contain a Vector<Pair<P,Q> >. Declaring virtual methods in this case, are not needed, but can still be used--with some extra overhead.

If you define AssociativeArray<P,Q> with a is-a relationship to Vector<Pair<P,Q> >, then you should define some virtual methods in Vector<T>, including a virtual destructor.

The use of virtual methods only matters when using objects polymorphically through pointers and references. See this page.

AssociativeArray<String,Int>* myDerivedMap = new AssociativeArray<String,Int>();
delete myDerivedMap; //NO virtual methods necessary here. using a pointer to derived class

Vector<Pair<String,Int> >* myBaseMap = new AssociativeArray<String,Int>();
delete myBaseMap; //virtual methods ARE necessary here. using a pointer to base class
like image 110
Geoff Montee Avatar answered Nov 15 '22 09:11

Geoff Montee


template<class T> 
Vector<T>::~Vector()
{
    delete [] data;
}

Note that you must use delete [] and not delete

like image 23
Armen Tsirunyan Avatar answered Nov 15 '22 10:11

Armen Tsirunyan


Should be

template <class T>
Vector<T>::~Vector() {
    delete[] data;
}
like image 1
πάντα ῥεῖ Avatar answered Nov 15 '22 10:11

πάντα ῥεῖ