2012-10-26 7 views
6

Tôi bắt đầu học c + + nhưng tôi bị mắc kẹt trong destructor. Chúng ta cần phải thực hiện một vector và đây là những gì tôi có cho đến nay.Thực hiện một destructor ảo trong 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]; 
} 

Giao diện được cung cấp và tôi cần triển khai. Nhưng điều này rất khác với C và Java, rằng tôi hơi lạc mất.


Trong cuộc tập trận thứ hai chúng ta cần phải thực hiện một cái gì đó như thế này bằng cách sử dụng) thực hiện Vector trước khi lớp có nguồn gốc và b) Vector như lớp thành phần, vì vậy có lẽ chúng ta sẽ sử dụng các destructor ảo trong một trong những cách tiếp cận ?

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

Chỉ cần lưu ý: bạn có thể cải thiện toán tử '= = bằng cách lấy đối số được truyền theo giá trị và sử dụng thành ngữ" sao chép và trao đổi "(http://stackoverflow.com/questions/3279543/ what-is-the-copy-and-swap-idiom) –

Trả lời

10

Trước hết, tại sao bạn nghĩ rằng destructor nên virtual? Bạn đang sử dụng đa hình?

Thứ hai, bạn đang sử dụng delete không chính xác cho mảng của mình.

Vì bạn sử dụng:

data = new T[length]; 

Bạn phải sử dụng cú pháp mảng:

delete [] data; 

Thứ ba, bạn cần phải đặt không gian tên trước mặt tất cả các định nghĩa chức năng lớp học của bạn:

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

Và chỉ với thông tin của bạn, bạn khai báo trình phá hủy như vậy ...

virtual ~Vector(void); 

Như tôi đã đề cập, virtual là không cần thiết trừ khi bạn đang sử dụng lớp này làm lớp cơ sở hoặc dẫn xuất theo cách đa hình. Để biết thêm thông tin về thời điểm bạn cần sử dụng virtual trình phá hủy, hãy xem answer to this question.

Ngoài ra, các thông số void cũng không cần thiết. Điều này thường được yêu cầu trong tiêu chuẩn C cũ, nhưng nó không có trong C++.

Bạn sẽ có thể khai báo nó như vậy:

~Vector(); 

Nếu bạn xác định AssociativeArray<P,Q> với một đã-một mối quan hệ-Vector<T>, sau đó bạn có thể chỉ đơn giản là làm cho lớp chứa một Vector<Pair<P,Q> >. Khai báo virtual phương pháp trong trường hợp này, không cần thiết, nhưng vẫn có thể được sử dụng - với một số chi phí phụ.

Nếu bạn xác định AssociativeArray<P,Q> với một là-một mối quan hệ-Vector<Pair<P,Q> >, sau đó bạn cần xác định một số phương pháp trong virtualVector<T>, bao gồm một destructor virtual.

Việc sử dụng các phương thức virtual chỉ quan trọng khi sử dụng đối tượng đa hình thông qua con trỏ và tham chiếu. Xem 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

Bạn có thể đi sâu hơn với phần 'virtual'/non-'virtual' không? – Acorbe

+1

Tôi liên kết với một câu hỏi khác giải thích theo cách khá thẳng thắn. –

+0

cảm ơn bạn. Thật vậy, tôi quan tâm nhiều hơn đến thiết kế, tức là tại sao anh ta không cho phép người ta kế thừa một cách an toàn từ 'Vector' của anh ta. Dù sao, tôi đã tìm thấy điểm tốt ở đây: http://stackoverflow.com/questions/1647298/why-dont-stl-containers-have-virtual-destructors – Acorbe

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

Lưu ý rằng bạn phải sử dụng delete [] và không delete

1

Nên

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