Niyə vektor ondan miras alınarsa, pis işləyəcək?
AI-dan cavab
sobes.tech Süni İntellekt
std::vector-dən irsənmə tövsiyə edilmir, çünki virtual destruktorlar və digər virtual funksiyalar mövcud deyil, bu da LSP (Liskov Substitutsiya Prinsipi) pozur və polimorf istifadə zamanı problemlərə səbəb olur.
Məsələn, problemlər:
-
Slicing problemi: Əgər törəmə sinif obyektini dəyər və ya referans vasitəsilə əsas sinif
std::vector-ə ötürsəniz, törəmə sinifə aid məlumatlar və davranışlar itəcək.#include <vector> #include <iostream> class MyVector : public std::vector<int> { public: int my_data = 100; // Virtual destruktor yoxdur ~MyVector() { std::cout << "MyVector destruktor" << std::endl; } }; void process_vector(std::vector<int> vec) { // Dəyər ilə qəbul edilir - slicing baş verir // MyVector destruktoru çağrılmayacaq std::cout << "std::vector emalı" << std::endl; } int main() { MyVector mv; mv.push_back(1); process_vector(mv); // MyVector obyektinin slicing-i return 0; } // Yalnız std::vector destruktoru çağrılır -
Virtual destruktorun olmaması: Əgər törəmə sinif obyektini əsas sinif göstəricisi ilə silsəniz, törəmə sinifin destruktoru çağrılmayacaq, bu da resurs sızmasına səbəb ola bilər.
#include <vector> #include <iostream> #include <memory> // unique_ptr üçün class DerivedVector : public std::vector<int> { public: int* resource; DerivedVector() : std::vector<int>(), resource(new int) { std::cout << "DerivedVector konstruktor" << std::endl; } // Virtual destruktor yoxdur ~DerivedVector() { std::cout << "DerivedVector destruktor" << std::endl; delete resource; // Çağrılmaya bilər } }; int main() { // Əsas sinif göstəricisi ilə silmə std::vector<int>* base_ptr = new DerivedVector(); // delete base_ptr ilə yalnız std::vector destruktoru çağrılır, // DerivedVector destruktoru çağrılmır, resource sızması delete base_ptr; // unique_ptr nümunəsi // std::unique_ptr<std::vector<int>> up = std::make_unique<DerivedVector>(); // Scope-dan çıxanda, unique_ptr delete çağıracaq və delete base_ptr; ilə eynidir. // Bu, vector virtual destruktoru yoxdursa, eyni problemi yaradar. return 0; } // resource üçün ayrılmış yaddaş sərbəst buraxılmayacaq -
Konstruktorlar:
std::vector-in konstruktorlarının (məsələn, kopyalama və köçürmə konstruktorları) davranışı, əgər törəmə sinif öz vəziyyətini və ya logikasını əlavə edirsə, gözləntilərə cavab verməyə bilər.
std::vector-dən irsənməyin yerinə, ən yaxşı yanaşmalar:
- Kompozisiya:
std::vector-i sinifin üzvü kimi istifadə et. Bu, interfeys və davranışı idarə etməyə imkan verir,std::vector-i içində istifadə etməklə.#include <vector> #include <iostream> class MyContainer { private: std::vector<int> data; int my_extra_data = 100; public: void add(int val) { data.push_back(val); } const std::vector<int>& get_data() const { // Giriş üçün return data; } // MyContainer destruktoru, data destruktorunu düzgün çağıracaq ~MyContainer() { std::cout << "MyContainer destruktor" << std::endl; } }; int main() { MyContainer mc; mc.add(1); std::cout << "Data ölçüsü: " << mc.get_data().size() << std::endl; return 0; } // MyContainer destruktoru çağrılır, o da std::vector destruktorunu çağırır - Boş funksiyalar və algoritmlər:
std::vector-in funksionallığını adi funksiyalar və ya standart algoritmlərlə genişləndirin.
Bu yanaşmalar daha çevik, daha təhlükəsiz və C++-də OOP və kitabxana dizayn prinsiplərinə uyğundur. Standart konteynerlər əsas sinif kimi istifadə üçün nəzərdə tutulmayıb.