C++ 包装STL以扩展

C++ 包装STL以扩展,c++,stl,wrapper,stdvector,C++,Stl,Wrapper,Stdvector,所以我读到从STL继承是个坏主意。但是,如何将STL类包装到其他类中以扩展它们呢。这主要是为了分离抽象层次 比如: template<class T> class MyVector{ public: T& last(){ return data[data.size() - 1] } bool include(T& element); //etc. private: vector<T> data; } 模板 类MyVector{ 公众: T&la

所以我读到从STL继承是个坏主意。但是,如何将STL类包装到其他类中以扩展它们呢。这主要是为了分离抽象层次

比如:

template<class T>
class MyVector{
public:
T& last(){
  return data[data.size() - 1]
}

bool include(T& element);

//etc.

private:
vector<T> data;
}
模板
类MyVector{
公众:
T&last(){
返回数据[data.size()-1]
}
bool包括(T&element);
//等等。
私人:
矢量数据;
}
这是个好主意吗?这是C++程序员经常做的吗?< /P>
谢谢。

是的,包装比继承好,但仅当您需要向现有数据结构添加状态时。否则,请添加非成员函数。这在C++编码标准()

第35条中有更详细的解释。 要添加状态,请选择组合而不是继承。诚然,必须为成员函数编写直通函数是很乏味的 您希望保留,但这样的实现比 使用公共或非公共继承

模板
类MyExtendedVector
{
公众:
//std::vector成员的传递函数
void some_existing_fun(){返回向量。some_existing_fun()}
//使用额外状态的新功能
作废一些_new _fun(){//您的实现在这里}
私人:
std::向量向量向量;
//额外状态,例如进行日志记录、缓存或其他操作
};
若要添加行为,请选择添加非EM ber函数而不是成员 功能

但是,请确保您的算法尽可能通用:

// if you CAN: write algorithm that uses iterators only 
// (and delegates to iterator category that container supports)
template<typename Iterator, typename T>
bool generic_contains(Iterator first, Iterator last, T const& elem)
{
    // implement using iterators + STL algorithms only
    return std::find(first, last, elem) != last;
}

// if you MUST: write algorithm that uses specific interface of container
template<typename T>
void vector_contains(std::vector<T> const& v, T const& elem)
{
    // implement using public interface of Container + STL algorithms
    return generic_contains(v.begin(), v.end(), elem);
}
//如果可以:编写只使用迭代器的算法
//(并委托给容器支持的迭代器类别)
模板
布尔泛型包含(迭代器优先、迭代器最后、T常量和元素)
{
//仅使用迭代器+STL算法实现
返回std::find(first,last,elem)!=last;
}
//若必须:编写使用容器特定接口的算法
模板
无效向量_包含(标准::向量常量和向量、T常量和元素)
{
//利用Container+STL算法的公共接口实现
返回泛型包含(v.begin(),v.end(),elem);
}

我只能为自己说话,但我还没有这样做,一般来说我可能不会建议这样做

在几乎所有情况下,基于迭代器的算法都更易于实现,并且将算法与容器分离。例如,假设您的
include
方法只是确定某个元素是否在向量中,您将根据容器的内容和搜索需要使用
find
binary\u search
lower\u bound


有时,我通过提供begin/end方法实现了一个对外部看起来像容器的类。在这种情况下,它有时确实有一个标准的底层容器,但您只实现了一个最小的公共接口来表示您的类实际建模的内容。

正如最后一个人回答的那样,我将避免这样做。我理解您的目标,您希望您的容器将一些更复杂的操作包装成更简单的方法,并且认为您可以在某个时候更改底层容器,而无需更改接口。尽管如此,您的对象应该为您的业务需求建模,然后这些对象的实现将使用最好的数据容器和访问模式。我想我要说的是,您最终不会重新使用这个新的vector类,因为您的业务需求的数据访问每次都会有所不同,您将再次使用一些标准的通用容器,如std::vector和基于迭代器的算法来访问数据

现在,如果有一些算法不存在,那么可以为特定项目编写基于迭代器的算法,然后保留可以重用的算法代码。下面显示了我编写的一个集合grep算法,它基于集合交集,但并不是我想要的。我可以下次再使用这个算法

#include <utility>
#include <algorithm>

//  this is a set grep meaning any items that are in set one
// will be pulled out if they match anything in set 2 based on operator pred 
template<typename _InputIterator1, typename _InputIterator2,
  typename _OutputIterator, typename _Compare>
  _OutputIterator
setGrep(_InputIterator1 __first1, _InputIterator1 __last1,
    _InputIterator2 __first2, _InputIterator2 __last2,
    _OutputIterator __result, _Compare __comp)
{
  while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first1, *__first2))
      ++__first1;
    else if (__comp(*__first2, *__first1))
      ++__first2;
    else
    {
      *__result = *__first1;
      ++__first1;
      ++__result;
    }
  return __result;
}
#包括
#包括
//这是一个集合grep,表示集合1中的任何项目
//根据操作员pred,如果它们与集合2中的任何内容匹配,将被拉出
模板
_输出器
setGrep(\u InputIterator1\u first1,\u InputIterator1\u last1,
_先输入2,后输入2,
_输出计数器(结果、比较、比较)
{
而(\uuuu first1!=\uuu last1&&uuu first2!=\uu last2)
如果(uuu comp(*uuu first1,*uuu first2))
++__第一个1;
否则如果(uuu comp(*uuu first2,*uuu first1))
++__前2名;
其他的
{
*__结果=*\uuu first1;
++__第一个1;
++__结果;
}
返回结果;
}

std::vector::back()
不,这不是首选方法。首选的方法是抽象出底层容器并对迭代器/整个范围进行操作,或者编写一个类外函数
bool include(std::vector const&v,T const&elem)
。他们不经常做这种事情,因为大多数时候,只要在适当的容器上使用适当的算法就足够了。标准库实现中使用的命名约定不需要模拟。包含双下划线的名称和以下划线开头并后跟大写字母的名称是为实现保留的,不会出现在用户代码中。
#include <utility>
#include <algorithm>

//  this is a set grep meaning any items that are in set one
// will be pulled out if they match anything in set 2 based on operator pred 
template<typename _InputIterator1, typename _InputIterator2,
  typename _OutputIterator, typename _Compare>
  _OutputIterator
setGrep(_InputIterator1 __first1, _InputIterator1 __last1,
    _InputIterator2 __first2, _InputIterator2 __last2,
    _OutputIterator __result, _Compare __comp)
{
  while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first1, *__first2))
      ++__first1;
    else if (__comp(*__first2, *__first1))
      ++__first2;
    else
    {
      *__result = *__first1;
      ++__first1;
      ++__result;
    }
  return __result;
}