开发者

Best way to insert items from a Derived class's constructor into a Base class's private std::vector?

开发者 https://www.devze.com 2022-12-26 02:18 出处:网络
I have these classes: class Base { ... private: std::vector<X> v; }; class Derived : public Base { Derived(X*, int n);

I have these classes:

class Base
{
...
private:
std::vector<X> v;
};

class Derived : public Base
{
Derived(X*, int n);
};

where the constructor of Derived is passed an array of item Xs, which I need to insert into my vector v in the Base class. (X is a smart pointer)

Currently I see two ways to do this:

  1. Create a function in Base: InsertItem(X*) that will insert an item into the vector (1 by 1)
  2. Create a vector in Derived that contains the full list, then get it into Base by moving the entire 开发者_如何转开发vector.

I dont see any advantages to #2, but was wondering if #1 was a good solution, or if there are better ways to do this.

Thanks!


There is a third option if you can modify Base. You could make the vector protected which will allow base classes full access:

class Base
{
...
protected:
    std::vector<X> v;
};

Your base class can now directly operate on v. If you need to expose much of the vector functionality to Derived, this is the easiest way.

If not, I would just add the one function (i.e. option #1) and would make it protected:

class Base
{
...

protected:
    void push_back(const X &x)
    {
        v.push_back(x);
    }

private:
    std::vector<X> v;
};


Another option is to create a (public or protected) constructor in base that will take the parameters and populate the vector directly. No intermediate vectors need be created or passed around.

class Base
{
 . . .
protected:
    Base(X* x,int n);
 . . .
};

class Derived : public Base
{
    Derived(X* xes, int n):Base(xes,n){};
};


If you can, I would create a protected constructor in Base that accepts the X* argument just like the Derived constructor, and then in Derived's constructor initialization list, pass the argument to Base's protected constructor and have it do the actual insertion.


If you want the container in the base class to remain private, you might consider adding a public (or protected) function in Base to allow the derived class to add a range. This way, the Base container type can be encapsulated (Derived doesn't need to know it's a vector), and Derived can still pass the whole thing down in one shot:

class Base
{
...
private:
    std::vector<X> v;

protected
    template <class iterator_t>
    void assign( iterator_t first, iterator_t last) {
        v.assign( first, last);
    }
};

class Derived : public Base
{
Derived(X* p, int n) {
    Base::assign( p, p+n);
}
};

It's not much of an encapsulation, but the container could be changed with a changing the derived class, and a derived class could easily be written that takes data in a form different than an array, if desired. And as zdan suggested this functionality could be part of public or protected constructor for Base if that makes more sense (which is likely).

The idea of using iterator ranges to represent the content or subset of a container is widespread in the STL.


You should set the member variable to be protected so that classes that inherit Base can access it. Alternatively keep the member variable private but add a protected accessor method to allow classes that inherit base to add to the vector etc

0

精彩评论

暂无评论...
验证码 换一张
取 消