Sobes.tech
Middle+

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:

  1. Kesishish muammosi: Turlangan sinf ob'ekti qiymat yoki referens orqali asosiy sinf std::vector ga 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
    
  2. Virtual destruktorning yo'qligi: Agar siz ob'ektni asosiy sinf std::vector orqali 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
    
  3. Konstruktorlar: std::vector konstruktorlarining (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::vector ni sinf a'zosi sifatida ishlatish. Bu yangi sinfning interfeysini va xulq-atvorini nazorat qilish imkonini beradi, std::vector ichida 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::vector funksionalligini 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.