2012-10-26 10 views
6

Ich fange an, C++ zu lernen, aber ich bin im Destruktor stecken. Wir müssen einen Vektor implementieren und das ist was ich bisher habe.Implementierung eines virtuellen Destruktors in C++

#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]; 
} 

Die Schnittstelle ist gegeben und ich muss es implementieren. Aber das ist so anders als in C und Java, dass ich ein bisschen verloren bin.


In der zweiten Übung, die wir so etwas wie diese mit a) der vorherige Vector Implementierung als abgeleitete Klasse und b) die Vector als Kompositionsklasse implementieren müssen, vielleicht werden wir den virtuellen Destruktor in einen der Ansätze verwenden ?

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;} 
}; 
+0

Nur ein Hinweis: Sie können Ihren 'Operator = ', indem sie das Argument übergibt Wert und mit dem "Copy-and-Swap" Idiom verbessern (http://stackoverflow.com/questions/3279543/ Was-ist-die-Kopie-und-Austausch-Idiom) –

Antwort

10

Zunächst einmal, warum denken Sie, dass die destructor sein sollte virtual sein sollte verwenden müssen? Verwenden Sie Polymorphie?

Zweitens verwenden Sie delete falsch für Ihr Array.

Da Sie verwendet:

data = new T[length]; 

Sie die Array-Syntax verwenden müssen:

delete [] data; 

Drittens müssen Sie den Namespace vor aller Klassenfunktionsdefinitionen setzen:

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

Und nur zu Ihrer Information, deklarieren Sie den Destruktor so ...

virtual ~Vector(void); 

Wie ich bereits erwähnt, virtual ist nicht erforderlich, es sei denn, Sie diese Klasse als Basis oder abgeleiteten Klasse in einer polymorphen Weise verwenden. Weitere Informationen darüber, wann Sie die Destruktoren virtual verwenden müssen, finden Sie unter answer to this question.

Darüber hinaus ist die void in den Parametern auch nicht erforderlich. Dies war früher im alten C-Standard erforderlich, aber nicht in C++.

sollten Sie in der Lage sein, es zu erklären, wie so:

~Vector(); 

Wenn Sie AssociativeArray<P,Q> mit einem hat-eine Beziehung zu Vector<T> definieren, dann können Sie einfach die Klasse eine Vector<Pair<P,Q> > enthalten machen. Deklarieren virtual Methoden in diesem Fall, sind nicht erforderlich, können aber immer noch verwendet werden - mit einigen zusätzlichen Aufwand.

Wenn Sie definieren AssociativeArray<P,Q> mit einem is-a Beziehung zu Vector<Pair<P,Q> >, dann sollten Sie einige virtual Methoden in Vector<T>, darunter ein virtual destructor definieren.

Die Verwendung von virtual Methoden ist nur wichtig, wenn Objekte polymorph durch Zeiger und Referenzen verwendet werden. Siehe 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 
+0

Könnten Sie bitte tiefer gehen mit dem 'virtuellen'/nicht-virtuellen Teil? – Acorbe

+1

Ich verlinkt auf eine andere Frage, die das auf eine ziemlich unkomplizierte Weise erklärt. –

+0

danke. In der Tat war ich mehr um Design besorgt, also warum sollte er nicht zulassen, dass man sicher von seinem 'Vector' erbt. Wie auch immer, ich fand gute Punkte hier: http://stackoverflow.com/questions/1647298/why-dont-stl-containers-have-virtual-destructors – Acorbe

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

Beachten Sie, dass delete [] und nicht delete

1

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