我可以使用std :: vector使用额外的default-parameter初始化元素吗?

时间:2015-02-20 16:55:56

标签: c++ c++11 vector stl containers

我目前正在开发自己的小框架,它具有以下设计模式: 每个对象都继承自LObject,并且具有父对象,当对象中的某些内容发生更改时,它会通知父对象。 这是一个例子:

class LObject
{
public:
    LObject(LObject* const _pParent = nullptr) :
        _mpParent(_pParent),
        _mChildrenCount(0)
    {
        if(parent() != nullptr)
            _mChildId = parent()->GenerateChildId();
    }

    unsigned int id() const { return _mChildId; }

protected:
    LObject* const parent() const { return _mpParent; }

    unsigned int selfId() const { return -1; }
    unsigned int GenerateChildId() const { return _mChildrenCount++; }

    virtual void ChildChanged(unsigned int _childId)
    {
        if(parent() != nullptr)
            parent()->ChildChanged(id());
    }
    virtual void ChildChanged() const
    {
        if(parent() != nullptr)
            parent()->ChildChanged(id());
    }

private:
    LObject* const _mpParent;
    unsigned int _mChildId;
    mutable unsigned int _mChildrenCount;
};

template <typename T>
class LType : public LObject
{
public:
    /// constructors
    LType(LObject* const _pParent=nullptr) : 
        LObject(_pParent),
        _mValue() 
    {}
    LType(const T& _rcValue, LObject* const _pParent=nullptr) :
        LObject(_pParent),
        _mValue(_rcValue)
    {}

    /// template type
    typedef T size_type;

    /// modify data
    void set(const T& _rcValue, bool _notifyParent=true)
    {
        _mValue = _rcValue; 
        if(_notifyParent) 
            ChildChanged();
    }
    void add(const T& _rcValue, bool _notifyParent=true); // same with +=

    /// get data
    const T& operator()() const; // returns _mValue

    /// operators (modify / get data)
    void operator=(const T& _rcValue); // same as set

private:
    T _mValue;
};

class SomeObject : public LObject
{
public:
    SomeObject(LObject* const _pParent = nullptr) : 
        LObject(_pParent), 
        someInt(this) 
    {}    

    LType<int> someInt;

    virtual void ChildChanged(unsigned int _childId)
    {
        LObject::ChildChanged();

        if(_childId == someInt.id())
            std::cout << "someInt changed!" << std::endl;
    }
};

int main(int argc, char* argv[])
{
    SomeObject obj;
    obj.someInt = 5;

    return 0;
}

输出:someInt已更改!

现在我想实现一个容器类,它应该像这样工作:

class SomeOtherObject : public LObject
{
public:
    SomeOtherObject (LObject* const _pParent = nullptr) : 
        LObject(_pParent), 
        someContainer(this) 
    {}   

    LContainer<LType<int>> someContainer;

    virtual void ChildChanged(unsigned int _childId)
    {
        LObject::ChildChanged();

        if(_childId == someContainer.id())
            std::cout << "someContainer changed!" << std::endl;
        if(_childId == someContainer[0].id())
            std::cout << "someContainer[0] changed!" << std::endl;
    }
};
int main(int argc, char* argv[])
{
    SomeOtherObject obj2;
    obj.someContainer.push_back(5);
    obj.someContainer[0].set(32);

    return 0;
}

Depending on the implementation the output should be: 
someContainer changed!
someContainer[0] changed!
or 
someContainer changed!
someContainer changed!

(目前我不在乎容器的元素是容器的子元素,还是与容器具有相同的父元素。)

因此,当您看到我希望容器像std :: vector一样工作时,唯一的区别是,在那里创建的对象(使用push_back或使用insert)知道它们的父级,并且容器知道它的父级。 (也许我甚至不关心容器知道它的父母,但我认为这是强制性的) 在最好的情况下,我想使用std :: vector。

我没有找到任何线索,比如在cplusplus参考中的std :: vector :: push_back参数列表末尾传递的默认值。 所以我的问题:

  • 是一种方式,我只是没找到它?
  • 如果不是,有没有比完全重新实现std :: vector更简单的方法?

我想为我的小框架创建一个容器类,尽可能少地实现STL中现有的所有方法。

我想像那样实现它(如果可能的话)

class LContainer : public std::vector, public LObject
{
    LContainer(LObject* const _pParent) :
        LObject(_pParent)
    {
        std::vector::addValuesWithDefaultParameter(parent()); // If something like that is available)
    }
};

编辑:这就是我解决问题的方法。 我继承了LObject和std :: vector,并重新实现了向向量添加内容的一些函数。 注意:私有继承用于阻止用户键入obj.container.std::vector::push_back(element);

/// LContainer.h
template <typename T>
class LContainer : public LObject, std::vector<T>
{
public:
    LContainer(LObject* const _pParent=nullptr);
    LContainer(unsigned int _startSize, LObject* const _pParent=nullptr);
    LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent=nullptr);

    /// Iterators
    using std::vector<T>::begin;
    using std::vector<T>::end;
    using std::vector<T>::rbegin;
    using std::vector<T>::rend;
    using std::vector<T>::cbegin;
    using std::vector<T>::cend;
    using std::vector<T>::crbegin;
    using std::vector<T>::crend;

    /// Capacity
    using std::vector<T>::size;
    using std::vector<T>::max_size;
    void resize(unsigned int _newSize, const T& _rcValue);
    using std::vector<T>::capacity;
    using std::vector<T>::empty;
    using std::vector<T>::reserve;
    using std::vector<T>::shrink_to_fit;

    /// Element access
    using std::vector<T>::operator [];
    using std::vector<T>::at;
    using std::vector<T>::front;
    using std::vector<T>::back;

    /// add elements
    void assign(unsigned int _count, const T& _rcValue);
    void push_back(const T& _rcValue);
    using std::vector<T>::pop_back;
    void insert(unsigned int _position, const T& _rcValue);
    void insert(unsigned int _position, unsigned int _count, const T& _rcValue);
    using std::vector<T>::erase;
    using std::vector<T>::swap;
    using std::vector<T>::clear;
    using std::vector<T>::emplace;
    using std::vector<T>::emplace_back;

    /// Allocator
    using std::vector<T>::get_allocator;

private:
    T _mElementDummy;
};

/// LContainer.inl file
template <typename T>
LContainer<T>::LContainer(LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{
    while(std::vector::size() < _startSize)
        std::vector::push_back(_mElementDummy);
}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{
    _mElementDummy = _rcValue;

    while(std::vector::size() < _startSize)
        std::vector::push_back(_mElementDummy);
}

template <typename T>
void LContainer<T>::resize(unsigned int _newSize, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::resize(_mElementDummy, _mElementDummy);
}

template <typename T>
void LContainer<T>::assign(unsigned int _count, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::assign(_count, _mElementDummy);
}
template <typename T>
void LContainer<T>::push_back(const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::insert(_position, _mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, unsigned int _count, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::insert(_position, _count, _mElementDummy);
}

2 个答案:

答案 0 :(得分:1)

std::vector::push_back无法获取其他参数。

我的建议:

  1. 使用合成代替std::vector的继承来定义LContainer

    class LContainer : public LObject
    {
        LContainer(LObject* const _pParent) : LObject(_pParent)
        {
        }
    
        // Member variable 
        std::vector<LObject*> containedObjects_;
    };
    
  2. LContainer中添加一项功能以添加对象。在此函数中,使用std::vector::push_back然后执行必要的其他处理。

    class LContainer : public LObject
    {
        LContainer(LObject* const _pParent) : LObject(_pParent)
        {
        }
    
        void addObject(LObject* object)
        {
           containedObjects_.push_back(object);
    
           // Do the additional processing.
           // ...
           //
        }
    
        // Member variable 
        std::vector<LObject*> containedObjects_;
    };
    

答案 1 :(得分:0)

我找到的最佳解决方案是继承LObject和std :: vector,并重新实现了向向量添加内容的一些函数。

std :: vector的功能是使用关键字using。

注意:私有继承用于阻止用户键入obj.container.std::vector::push_back(element);

/// LContainer.h
template <typename T>
class LContainer : public LObject, std::vector<T>
{
public:
    LContainer(LObject* const _pParent=nullptr);
    LContainer(unsigned int _startSize, LObject* const _pParent=nullptr);
    LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent=nullptr);

    /// Iterators
    using std::vector<T>::begin;
    using std::vector<T>::end;
    using std::vector<T>::rbegin;
    using std::vector<T>::rend;
    using std::vector<T>::cbegin;
    using std::vector<T>::cend;
    using std::vector<T>::crbegin;
    using std::vector<T>::crend;

    /// Capacity
    using std::vector<T>::size;
    using std::vector<T>::max_size;
    void resize(unsigned int _newSize, const T& _rcValue);
    using std::vector<T>::capacity;
    using std::vector<T>::empty;
    using std::vector<T>::reserve;
    using std::vector<T>::shrink_to_fit;

    /// Element access
    using std::vector<T>::operator [];
    using std::vector<T>::at;
    using std::vector<T>::front;
    using std::vector<T>::back;

    /// add elements
    void assign(unsigned int _count, const T& _rcValue);
    void push_back(const T& _rcValue);
    using std::vector<T>::pop_back;
    void insert(unsigned int _position, const T& _rcValue);
    void insert(unsigned int _position, unsigned int _count, const T& _rcValue);
    using std::vector<T>::erase;
    using std::vector<T>::swap;
    using std::vector<T>::clear;
    using std::vector<T>::emplace;
    using std::vector<T>::emplace_back;

    /// Allocator
    using std::vector<T>::get_allocator;

private:
    T _mElementDummy;
};

/// LContainer.inl file
template <typename T>
LContainer<T>::LContainer(LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{
    while(std::vector::size() < _startSize)
        std::vector::push_back(_mElementDummy);
}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent) :
    LObject(_pParent),
    std::vector<T>(),
    _mElementDummy(_pParent)
{
    _mElementDummy = _rcValue;

    while(this->size() < _startSize)
        std::vector::push_back(_mElementDummy);
}

template <typename T>
void LContainer<T>::resize(unsigned int _newSize, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::resize(_mElementDummy, _mElementDummy);
}

template <typename T>
void LContainer<T>::assign(unsigned int _count, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::assign(_count, _mElementDummy);
}
template <typename T>
void LContainer<T>::push_back(const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::insert(_position, _mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, unsigned int _count, const T& _rcValue)
{
    _mElementDummy = _rcValue;
    std::vector::insert(_position, _count, _mElementDummy);
}