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?

Mengomentari pertanyaan (9)
Larutan

Virtual destruktor berguna ketika anda mungkin berpotensi menghapus sebuah instance dari sebuah kelas yang diturunkan melalui pointer ke kelas dasar:

class Base 
{
    // some virtual methods
};

class Derived : public Base
{
    ~Derived()
    {
        // Do some important cleanup
    }
};

Di sini, anda'll pemberitahuan bahwa saya tidak't menyatakan Dasar's destructor untuk menjadi virtual. Sekarang, let's silahkan lihat pada cuplikan berikut:

Base *b = new Derived();
// use b
delete b; // Here's the problem!

Karena Dasar's destructor tidak virtual dan b adalah Dasar* menunjuk Berasal objek delete b telah undefined perilaku:

[hapus b], jika statis jenis objek yang akan dihapus adalah berbeda dari tipe dinamis, statis jenis akan menjadi dasar kelas dinamis jenis objek yang akan dihapus dan statis jenis akan memiliki virtual destructor atau perilaku yang tidak terdefinisi.

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.

Komentar (10)

Virtual constructor tidak mungkin tapi virtual destructor adalah mungkin. Mari kita bereksperimen....


#include 

using namespace std;

class Base
{
public:
    Base(){
        cout 
Komentar (5)

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.

Komentar (7)

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.

Komentar (2)

Membuat virtual destructor setiap kali anda kelas adalah polimorfik.

Komentar (0)

Menelepon destructor melalui pointer ke kelas dasar

struct Base {
  virtual void f() {}
  virtual ~Base() {}
};

struct Derived : Base {
  void f() override {}
  ~Derived() override {}
};

Base* base = new Derived;
base->f(); // calls Derived::f
base->~Base(); // calls Derived::~Derived

Virtual destructor panggilan tidak berbeda dari yang lain maya panggilan fungsi.

Untuk base->f(), panggilan akan dikirim ke Berasal::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 memanggil base->~Dasar() yang akan diberangkatkan ke Berasal::~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:

// library.hpp

struct Base {
  virtual void f() = 0;

protected:
  ~Base() = default;
};

void CallsF(Base& base);
// CallsF is not going to own "base" (i.e. call "delete &base;").
// It will only call Base::f() so it doesn't need to access Base::~Base.

//-------------------
// application.cpp

struct Derived : Base {
  void f() override { ... }
};

int main() {
  Derived derived;
  CallsF(derived);
  // No need for virtual destructor here as well.
}
Komentar (2)

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.

Komentar (4)

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.


 #include
 using namespace std;
 class B{
    public:
       B(){
          cout
Komentar (4)

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:

Base *myObj = new Derived();
// Some code which is using myObj object
myObj->fun();
//Now delete the object
delete myObj ; 

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.

Komentar (0)

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


#include "stdafx.h"
#include
using namespace std;
// program to convert the lower to upper orlower
class convertch
{
public:
  //void convertch(){};
  virtual char* convertChar() = 0;
  ~convertch(){};
};

class MakeLower :public convertch
{
public:
  MakeLower(char *passLetter)
  {
    tolower = true;
    Letter = new char[30];
    strcpy(Letter, passLetter);
  }

  virtual ~MakeLower()
  {
    cout
Komentar (0)

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).

Komentar (0)

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:

Base Constructor Called
Derived constructor called
Derived destructor called
Base Destructor called
Komentar (0)

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).


#include 
using namespace std;

struct a
{
    ~a() {}

    unsigned long long i;
};

struct b : a
{
    ~b() {}

    unsigned long long j;
};

struct c : b
{
    ~c() {}

    virtual void m3() {}

    unsigned long long k;
};

struct d : c
{
    ~d() {}

    virtual void m4() {}

    unsigned long long l;
};

int main()
{
    cout 
Komentar (0)

Saya pikir inti dari pertanyaan ini adalah tentang metode virtual dan polimorfisme, tidak destructor khusus. Berikut ini adalah contoh lebih jelas:


class A
{
public:
    A() {}
    virtual void foo()
    {
        cout 
Komentar (3)

ketika anda perlu untuk memanggil class turunan destruktor dari kelas dasar. anda perlu untuk menyatakan virtual dasar kelas destructor di kelas dasar.

Komentar (0)

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.

Komentar (1)