Lebih
Ketika menggunakan virtual destruktor?
Saya memiliki pemahaman yang solid dari yang paling OO teori tapi satu hal yang membingungkan saya adalah virtual destruktor.
Saya berpikir bahwa destructor selalu dipanggil tidak peduli apa dan untuk setiap objek dalam rantai.
Ketika anda dimaksudkan untuk membuat mereka virtual dan mengapa?
1409
16
Virtual destruktor berguna ketika anda mungkin berpotensi menghapus sebuah instance dari sebuah kelas yang diturunkan melalui pointer ke kelas dasar:
Di sini, anda'll pemberitahuan bahwa saya tidak't menyatakan Dasar's destructor untuk menjadi
virtual
. Sekarang, let's silahkan lihat pada cuplikan berikut:Karena Dasar's destructor tidak
virtual
danb
adalahDasar*
menunjukBerasal
objekdelete b
telah undefined perilaku:Di sebagian besar implementasi, panggilan untuk destructor akan diselesaikan seperti non-virtual kode, yang berarti bahwa destruktor dari kelas dasar akan dipanggil tetapi tidak salah satu dari kelas yang diturunkan, sehingga sumber-sumber kebocoran.
Untuk meringkas, selalu membuat kelas dasar' destruktor
virtual
ketika mereka're dimaksudkan untuk dimanipulasi polymorphically.Jika anda ingin mencegah penghapusan sebuah instance melalui kelas dasar pointer, anda dapat membuat kelas dasar destructor dilindungi dan nonvirtual; dengan demikian, compiler tidak't membiarkan anda menelepon
delete
pada kelas dasar pointer.Anda dapat mempelajari lebih lanjut tentang dunia maya dan virtual base kelas destructor di artikel ini dari Ramuan Sutter.
Virtual constructor tidak mungkin tapi virtual destructor adalah mungkin. Mari kita bereksperimen....
Menyatakan destruktor virtual di polimorfik kelas dasar. Ini adalah Item 7 di Scott Meyers' Efektif C++. Meyers masuk menyimpulkan bahwa jika sebuah class memiliki setiap fungsi virtual, harus memiliki virtual destructor, dan bahwa kelas tidak dirancang untuk menjadi dasar kelas atau tidak dirancang untuk digunakan polymorphically harus tidak menyatakan virtual destruktor.
Juga perlu diketahui bahwa menghapus kelas dasar pointer ketika tidak ada virtual destructor akan mengakibatkan undefined perilaku. Sesuatu yang saya pelajari baru-baru ini:
https://stackoverflow.com/questions/408196/how-should-overriding-delete-in-c-behave
I've telah menggunakan C++ selama bertahun-tahun dan saya masih mengelola untuk menggantung diri.
Membuat virtual destructor setiap kali anda kelas adalah polimorfik.
Menelepon destructor melalui pointer ke kelas dasar
Virtual destructor panggilan tidak berbeda dari yang lain maya panggilan fungsi.
Untuk
base->f()
, panggilan akan dikirim keBerasal::f()
, dan's yang sama untuk dasar->~Dasar()- nya meng-override fungsi -
Berasal::~Turunan()` akan disebut.Yang sama terjadi ketika destructor dipanggil secara tidak langsung, misalnya
menghapus dasar;
.Hapus
pernyataan akan memanggilbase->~Dasar()
yang akan diberangkatkan keBerasal::~Turunan()
.Abstrak kelas dengan non-virtual destructor
Jika anda tidak akan menghapus objek melalui pointer ke kelas dasar - maka tidak ada kebutuhan untuk memiliki sebuah virtual destructor. Hanya membuat
dilindungi
sehingga tidak't disebut sengaja:Saya suka berpikir tentang interface dan implementasi antarmuka. Dalam C++ berbicara antarmuka virtual murni kelas. Destructor adalah bagian dari antarmuka dan diharapkan untuk dilaksanakan. Oleh karena itu destructor harus murni virtual. Bagaimana dengan constructor? Konstruktor adalah benar-benar bukan bagian dari antarmuka karena objek selalu diturunkan secara eksplisit.
Untuk menjadi sederhana, Virtual destructor adalah untuk merusak sumber daya dalam urutan yang tepat, pada saat anda menghapus kelas dasar pointer yang menunjuk ke objek kelas turunan.
Kata kunci Virtual untuk destructor adalah diperlukan ketika anda ingin berbeda destruktor harus mengikuti urutan yang tepat saat objek sedang dihapus melalui kelas dasar pointer. misalnya:
Jika anda berasal dari kelas destructor adalah virtual maka benda akan destrcuted dalam rangka(pertama berasal objek maka basis ). Jika anda berasal dari kelas destructor TIDAK virtual maka hanya dasar kelas objek yang akan dihapus(karena pointer dari kelas dasar "Dasar *myObj"). Jadi akan ada kebocoran memori untuk yang berasal objek.
Apa itu virtual destructor atau cara menggunakan virtual destructor
Kelas destruktor adalah fungsi dengan nama yang sama dari kelas sebelumnya dengan ~ yang akan mengalokasikan memori yang dialokasikan oleh kelas. Mengapa kita perlu virtual destructor
Lihat contoh berikut dengan beberapa fungsi virtual
Sampel juga memberitahu bagaimana anda dapat mengkonversi surat ke atas atau bawah
Virtual dasar kelas destruktor adalah "praktek terbaik" - anda harus selalu menggunakan mereka untuk menghindari (sulit untuk mendeteksi) kebocoran memori. Menggunakan mereka, anda dapat yakin semua destruktor dalam rantai warisan dari kelas anda yang beeing disebut (dalam urutan yang tepat). Mewarisi dari kelas dasar menggunakan virtual destructor membuat destruktor dari mewarisi kelas secara otomatis virtual, juga (jadi anda tidak perlu mengetik ulang 'maya' dalam mewarisi kelas destructor deklarasi).
Jika anda menggunakan
shared_ptr
(hanya shared_ptr, tidak unique_ptr), anda don't harus memiliki dasar kelas virtual destructor:``
include
include
menggunakan namespace std;
kelas Dasar { umum: Base(){ cout << "Dasar Konstruktor yang Disebut\n"; } ~Dasar(){ // tidak virtual cout << "Dasar Destructor dipanggil\n"; } };
kelas Turunan: publik Dasar { umum: Berasal(){ cout << "Berasal konstruktor yang disebut\n"; } ~Turunan(){ cout << "Berasal destructor dipanggil\n"; } };
int main() { shared_ptr b(baru Diperoleh()); } `` output:
Saya pikir itu akan bermanfaat untuk mendiskusikan "undefined" perilaku, atau setidaknya "crash" undefined perilaku yang mungkin terjadi saat menghapus melalui kelas dasar(/struct) tanpa virtual destructor, atau lebih tepatnya tidak ada vtable. Kode di bawah ini daftar beberapa sederhana struct (hal yang sama akan berlaku untuk kelas).
Saya pikir inti dari pertanyaan ini adalah tentang metode virtual dan polimorfisme, tidak destructor khusus. Berikut ini adalah contoh lebih jelas:
ketika anda perlu untuk memanggil class turunan destruktor dari kelas dasar. anda perlu untuk menyatakan virtual dasar kelas destructor di kelas dasar.
Setiap kelas yang diwariskan secara terbuka, polimorfik atau tidak, harus memiliki virtual destructor. Dengan kata lain, jika hal ini dapat ditunjukkan oleh kelas dasar pointer, basis kelas harus memiliki sebuah virtual destructor.
Jika virtual, kelas yang diturunkan destructor dipanggil, maka dasar kelas konstruktor. Jika tidak virtual, hanya dasar kelas destructor dipanggil.