Pembaruan: shared_ptr dalam contoh ini seperti yang ada di Boost, tetapi tidak mendukung shared_polymorphic_downcast (atau dynamic_pointer_cast atau static_pointer_cast dalam hal ini)!
Saya mencoba untuk menginisialisasi penunjuk bersama ke kelas turunan tanpa kehilangan jumlah referensi:
struct Base { };
struct Derived : public Base { };
shared_ptr<Base> base(new Base());
shared_ptr<Derived> derived;
// error: invalid conversion from 'Base* const' to 'Derived*'
derived = base;
Sejauh ini baik. Saya tidak berharap C ++ secara implisit mengubah Base * menjadi Derived *. Namun, saya menginginkan fungsionalitas yang diekspresikan oleh kode (yaitu, mempertahankan jumlah referensi sambil men-downcast penunjuk dasar). Pikiran pertama saya adalah menyediakan operator cor di Base sehingga konversi implisit ke Derived dapat terjadi (untuk pedants: Saya akan memeriksa apakah down cast valid, jangan khawatir):
struct Base {
operator Derived* ();
}
// ...
Base::operator Derived* () {
return down_cast<Derived*>(this);
}
Yah, itu tidak membantu. Sepertinya kompiler mengabaikan operator typecast saya. Ada ide bagaimana saya bisa membuat tugas shared_ptr bekerja? Untuk poin tambahan: tipe apa Base* const
itu? const Base*
Saya mengerti, tapi Base* const
? Apa yang dimaksud const
dalam kasus ini?
Jawaban:
Anda bisa menggunakan
dynamic_pointer_cast
. Ini didukung olehstd::shared_ptr
.Dokumentasi: https://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast
Juga, saya tidak merekomendasikan menggunakan operator cor di kelas dasar. Transmisi implisit seperti ini mungkin menjadi sumber bug dan kesalahan.
-Update: Jika tipenya tidak polimorfik,
std::static_pointer_cast
boleh digunakan.sumber
std::shared_ptr
. Tapi dari komentar jawaban pertama saya menyimpulkan bahwa dia tidak menggunakan boost, jadi dia mungkin menggunakanstd::shared_ptr
.Saya berasumsi Anda menggunakan
boost::shared_ptr
... Saya pikir Anda ingindynamic_pointer_cast
ataushared_polymorphic_downcast
.Namun, ini membutuhkan tipe polimorfik.
const Base *
adalah penunjuk yang bisa berubah ke sebuah konstantaBase
.Base const *
adalah penunjuk yang bisa berubah ke sebuah konstantaBase
.Base * const
adalah penunjuk konstan ke yang bisa berubahBase
.Base const * const
adalah penunjuk konstan ke sebuah konstantaBase
.Berikut contoh minimalnya:
Saya tidak yakin apakah itu disengaja bahwa contoh Anda membuat instance dari tipe dasar dan melemparkannya, tetapi berfungsi untuk menggambarkan perbedaan dengan baik.
The
static_pointer_cast
kehendak "lakukan saja". Ini akan mengakibatkan perilaku tidak terdefinisi (Derived*
menunjuk ke memori yang dialokasikan untuk dan diinisialisasi olehBase
) dan kemungkinan besar akan menyebabkan crash, atau lebih buruk. Jumlah referensibase
akan bertambah.Ini
dynamic_pointer_cast
akan menghasilkan pointer nol. Jumlah referensibase
tidak akan berubah.The
shared_polymorphic_downcast
akan memiliki hasil yang sama sebagai pemain statis, tetapi akan memicu sebuah pernyataan, daripada tampak untuk berhasil dan yang mengarah ke perilaku undefined. Jumlah referensibase
akan bertambah.Lihat (tautan mati) :
sumber
shared_ptr
konstruktor lain (mengambilstatic_cast_tag
dandynamic_cast_tag
), tidak banyak yang dapat Anda lakukan. Apa pun yang Anda lakukan di luarshared_ptr
tidak akan dapat mengelola refcount tersebut. - Dalam desain OO yang "sempurna", Anda selalu dapat menggunakan tipe dasar, dan tidak perlu mengetahui atau peduli apa tipe turunannya, karena semua fungsinya diekspos melalui antarmuka kelas dasar. Mungkin Anda hanya perlu memikirkan kembali mengapa Anda perlu down-cast di tempat pertama.Jika seseorang sampai di sini dengan boost :: shared_ptr ...
Ini adalah bagaimana Anda bisa downcast ke Boost shared_ptr diturunkan. Asumsi Derived mewarisi dari Base.
Pastikan class / struct 'Base' memiliki setidaknya satu fungsi virtual. Penghancur virtual juga berfungsi.
sumber