所以我读到STL的继承是一个坏主意。但是如何将STL类包装在其他类中以扩展它们呢。这主要是为了分离抽象层次,等等。
类似的东西:
template<class T>
class MyVector{
public:
T& last(){
return data[data.size() - 1]
}
bool include(T& element);
//etc.
private:
vector<T> data;
}
这是个好主意吗?这是c ++程序员经常做的事吗?
谢谢。
答案 0 :(得分:3)
是的,包装比继承更好,但前提是您需要将状态添加到现有数据结构中。否则,添加非成员函数。这在C ++编码标准(Amazon)
的第35项中有更详细的解释要添加状态,请选择合成而不是继承。不可否认,必须为成员函数编写passthrough函数是很繁琐的 你想保留,但这样的实现比它更好,更安全 使用公共或非公共继承。
template<typename T>
class MyExtendedVector
{
public:
// pass-through functions for std::vector members
void some_existing_fun() { return vec_.some_existing_fun(); }
// new functionality that uses extra state
void some_new_fun() { // your implementation here }
private:
std::vector<T> vec_;
// extra state e.g. to do logging, caching, or whatever
};
要添加行为,请更喜欢添加非成员函数而不是成员 功能
但请确保尽可能使算法更通用:
// 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);
}
答案 1 :(得分:3)
我只能为自己说话,但我没有这样做,我可能不会一般地建议。
几乎在所有情况下,基于迭代器的算法都更容易实现并且将算法与容器分开。例如,假设您的include
方法只是确定元素是否在向量中,您可以使用find
,binary_search
或lower_bound
,具体取决于容器的内容和搜索需求。
有时我已经通过提供开始/结束方法实现了一个看起来的类,就像外部世界的容器一样。在这种情况下,它有时会有一个标准的容器底层,但是你只需要实现一个最小的公共接口来表示你的类实际建模的内容。
答案 2 :(得分:2)
我会避免这样做,因为最后一个人回复了。我知道你要去哪里你的容器将一些更复杂的操作包装成更简单的方法,并且认为你可以在某些时候更改底层容器而不必更改你的接口。但是,话虽如此,您的对象应该建模您的业务需求,然后这些对象的实现将使用任何数据容器和访问模式是最好的。我想我所说的是你不会最终重新使用这个新的矢量类,因为你的业务需求的数据访问每次都会有所不同,你将再次使用一些标准的通用容器,如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;
}