Nima uchun vektor undan meros olinsa, u yaxshi ishlamaydi?
sobes.tech AI
AIdan javob
std::vector dan kalıtimi tavsiya etilmaydi, chunki u virtual destruktorlar va boshqa virtual funksiyalarni o'z ichiga olmaydi, bu Liskov almashtirish prinsipi'ni buzadi va polimorfik foydalanishda muammolarga olib keladi.
Muammo misollari:
-
Kesishish muammosi: Turlangan sinf ob'ekti qiymat yoki referens orqali asosiy sinf
std::vectorga o'tkazilganda, turlangan sinfga xos ma'lumotlar va xulq-atvorlar yo'qoladi.#include <vector> #include <iostream> class MyVector : public std::vector<int> { public: int my_data = 100; // Virtual destruktor yo'q ~MyVector() { std::cout << "MyVector destruktor" << std::endl; } }; void process_vector(std::vector<int> vec) { // Qiymat bilan o'tkazish - kesishish // MyVector destruktor chaqirilmaydi std::cout << "std::vector ni ishlash" << std::endl; } int main() { MyVector mv; mv.push_back(1); process_vector(mv); // MyVector ob'ekti kesiladi return 0; } // Faqat std::vector destruktor chaqiriladi -
Virtual destruktorning yo'qligi: Agar siz ob'ektni asosiy sinf
std::vectororqali o'chirsangiz, turlangan sinf destruktori chaqirilmaydi, bu resurslar oqishini keltirib chiqarishi mumkin.#include <vector> #include <iostream> #include <memory> // unique_ptr uchun class DerivedVector : public std::vector<int> { public: int* resource; DerivedVector() : std::vector<int>(), resource(new int) { std::cout << "DerivedVector konstruktor" << std::endl; } // Virtual destruktor yo'q ~DerivedVector() { std::cout << "DerivedVector destruktor" << std::endl; delete resource; // Chaqirilmaydi } }; int main() { // Asosiy sinf ko'rsatkichi orqali o'chirish std::vector<int>* base_ptr = new DerivedVector(); // delete bilan delete qilganda, faqat std::vector destruktor chaqiriladi, // DerivedVector destruktori chaqirilmaydi, resurslar oqib ketadi delete base_ptr; // Misol: std::unique_ptr bilan // std::unique_ptr<std::vector<int>> up = std::make_unique<DerivedVector>(); // up->push_back(5); // Scope tugagach, unique_ptr delete chaqiradi va base_ptr ni o'chiradi. // Bu, vector virtual destruktor bo'lmasa, muammoni takrorlaydi. return 0; } // resource uchun ajratilgan xotira bo'shatilmaydi -
Konstruktorlar:
std::vectorkonstruktorlarining (masalan, nusxa ko'chirish, ko'chirish) xulq-atvori, agar u o'z holati yoki logikasini qo'shgan bo'lsa, kutganingizga mos kelmasligi mumkin.
std::vector dan meros olish o'rniga, eng yaxshi yondashuvlar:
- Kompozitsiya:
std::vectorni sinf a'zosi sifatida ishlatish. Bu yangi sinfning interfeysini va xulq-atvorini nazorat qilish imkonini beradi,std::vectorichida ishlatish orqali.#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 { // Kerak bo'lsa, vektorga kirish return data; } // MyContainer destruktori, data destruktorini to'g'ri chaqiradi ~MyContainer() { std::cout << "MyContainer destruktor" << std::endl; } }; int main() { MyContainer mc; mc.add(1); std::cout << "Ma'lumotlar o'lchami: " << mc.get_data().size() << std::endl; return 0; } // MyContainer destruktori chaqiriladi, u o'z navbatida std::vector destruktorini chaqiradi - Erkin funksiyalar va algoritmlar:
std::vectorfunksionalligini oddiy funksiyalar yoki standart algoritmlar yordamida kengaytirish.
Ushbu yondashuvlar yanada moslashuvchan, xavfsiz va C++ da OOP va kutubxona dizayni tamoyillariga mos keladi. Standart konteynerlar, asosiy sinf sifatida foydalanish uchun mo'ljallanmagan.