Example of writing wrapper class for vector in C++

#include <vector>
#include <stdexcept>

template <typename T>
class MyVector {
private:
    std::vector<T> vec;

public:
    // Constructor
    MyVector() {}

    // Constructor with size
    MyVector(size_t size) : vec(size) {}

    // Constructor with size and initial value
    MyVector(size_t size, const T& value) : vec(size, value) {}

    // Add an element to the end of the vector
    void push_back(const T& value) {
        vec.push_back(value);
    }

    // Access an element at a specific index with bounds checking
    T& at(size_t index) {
        if (index >= size()) {
            throw std::out_of_range("Index out of range");
        }
        return vec.at(index);
    }

    // Access an element at a specific index without bounds checking
    T& operator[](size_t index) {
        return vec[index];
    }

    // Get the size of the vector
    size_t size() const {
        return vec.size();
    }

    // Check if the vector is empty
    bool empty() const {
        return vec.empty();
    }

    // Clear the vector
    void clear() {
        vec.clear();
    }

    // Other vector-like methods can be added as needed

    // Iterator support
    using iterator = typename std::vector<T>::iterator;
    iterator begin() {
        return vec.begin();
    }

    iterator end() {
        return vec.end();
    }
};
#include <iostream>

int main() {
    MyVector<int> myVec;
    myVec.push_back(10);
    myVec.push_back(20);

    try {
        std::cout << myVec.at(0) << std::endl; // Should print 10
        std::cout << myVec.at(1) << std::endl; // Should print 20
        std::cout << myVec.at(2) << std::endl; // Should throw out_of_range
    } catch (const std::out_of_range& e) {
        std::cerr << "Exception caught: " << e.what() << std::endl;
    }

    return 0;
}

Deriving a class from std::vector is generally not recommended in C++. The Standard Library containers, like std::vector, are not designed to be base classes, and they lack a virtual destructor. Attempting to derive from them can lead to issues related to object slicing and other unexpected behavior.

Instead of deriving from std::vector, it's better to encapsulate it within your wrapper class, as shown in the example I provided earlier. Encapsulation is one of the fundamental principles of object-oriented programming, and it allows you to provide controlled access and customization while avoiding the problems associated with inheritance.

Here are some reasons why deriving from std::vector is not a good idea:

  1. Lack of a Virtual Destructor: std::vector doesn't have a virtual destructor. When you derive a class from it and attempt to use polymorphism, you can encounter issues with resource management and memory leaks.

  2. Risk of Object Slicing: If you pass an instance of a derived class by value and it gets sliced down to a base class object, you lose the derived class's specific functionality.

  3. Limited Customization: Deriving from std::vector doesn't provide a clean way to customize its behavior. Instead, you can wrap std::vector in your own class and add the desired functionality while maintaining encapsulation.

  4. Compatibility and Portability: Code that relies on derived classes of standard containers may not be portable or compatible with other libraries or future C++ standards.

By encapsulating std::vector and providing a well-defined interface, you can control how the container is used and avoid these issues. This approach also makes it easier to adapt your implementation to different container types or libraries in the future without affecting the rest of your code.